For a moment, I thought they had added true multiple value return to C++. I am sooo glad they didn't. The lisp folks added it way back, and it has been an ugly scar on the language ever since. Why do real multi-value returns suck? because they don't compose well, they're awkward as all heck to use, and require wrapping certain function calls in really weird constructs. The PROPER way to do multiple values is to retur…
It's funny, your comment uses "true MRV" for language-level special-casing by opposition to a matched (or even just python-style unpacked) data-structure, whereas I've always thought the latter was "true MRV". Either way, we do agree on MRV being a language-level special case being a hack. Even PHP isn't that bad — though the unpacking is macro-ish bleh.
Returning multiple values from functions in C++
41–50 of 67 posts
Re: Returning multiple values from functions in C++
#42For a moment, I thought they had added true multiple value return to C++. I am sooo glad they didn't. The lisp folks added it way back, and it has been an ugly scar on the language ever since. Why do real multi-value returns suck? because they don't compose well, they're awkward as all heck to use, and require wrapping certain function calls in really weird constructs. The PROPER way to do multiple values is to retur…
Multiple values are not "just" an optimization hack, they are designed to be convenient to use. I don't know which construct you find "weird". Multiple-value-bind is a descriptive name which is long to type but this does not matter (type m-v-b + auto-complete). Typical example: you read a line in a file. The line you get is terminated either by a newline character or by the end-of file. The implementation of read-lin…
Re: Returning multiple values from functions in C++
#43Earlier quoted context omitted.
That's not the fault of optional though. It's because with the optional version you're creating (and destroying) a new string each iteration of the loop. Something like this (untested) should be much closer to the non-optional version: #include #include #include using namespace std; using namespace boost; optional getline_(istream &st, string& line) { if(getline(st, line)) return line; return none; } int main() { int…
Which more or less removes any benefit for using optional, unfortunately.
Re: Returning multiple values from functions in C++
#44Ada has in, out and in/out parameters which adds a little more semantic to C and C++'s pointer parameters. Author mentions Common Lisp's multiple values, and one of the main feature of multiple values is that they are optional: the caller does not need to use secondary values. Even though floor returns 2 values, the following is a valid expression: (+ (floor x) 2) Only the primary value is used. A compiler typically…
Sometimes Lisp can get annoying though. I've used libraries where a function might return 5-6 values and I only need the first and last. I need to bind all of them and then (declare (ignore...)) the useless bits otherwise I get compiler warnings. It's an annoyance, because I always feel the general ethos of Lisp is to eliminate tedious typing and multiple value returns frequently add a lot of cruft.
There are libraries out there that provide syntactic sugar for Common Lisp, which is often discarded because (i) they define their own "ghetto" dialect of Lisp (ii) it is in fact not very important to waste a character or two. Aesthetics alone is not a goal.
For multiple values, you might still use a list instead, in which case you are back to the usual way of accessing data:
(let ((list (multiple-value-list (get-decoded-time))))
(format t "Year: ~A~%Seconds: ~A" (sixth list) (first list)))
If you only want to access a particular value, use "nth-value" (not possible in your example, of course).Re: Returning multiple values from functions in C++
#45I am a bit surprised exceptions were not mentioned in the context of returning an error value.
The idea was to show things that actually make sense as return values / statuses rather than exceptions. I surely wouldn't throw an exception for "getline reached EOF"
Re: Returning multiple values from functions in C++
#46For a moment, I thought they had added true multiple value return to C++. I am sooo glad they didn't. The lisp folks added it way back, and it has been an ugly scar on the language ever since. Why do real multi-value returns suck? because they don't compose well, they're awkward as all heck to use, and require wrapping certain function calls in really weird constructs. The PROPER way to do multiple values is to retur…
Multiple values are not "just" an optimization hack, they are designed to be convenient to use. I don't know which construct you find "weird". Multiple-value-bind is a descriptive name which is long to type but this does not matter (type m-v-b + auto-complete). Typical example: you read a line in a file. The line you get is terminated either by a newline character or by the end-of file. The implementation of read-lin…
Re: Returning multiple values from functions in C++
#47Earlier quoted context omitted.
It's funny, your comment uses "true MRV" for language-level special-casing by opposition to a matched (or even just python-style unpacked) data-structure, whereas I've always thought the latter was "true MRV". Either way, we do agree on MRV being a language-level special case being a hack. Even PHP isn't that bad — though the unpacking is macro-ish bleh.
If you wrap your data in a list or a tuple, it is still a single value. It makes sense to talk about true MRV in languages that support it, like Ada, Forth and others... ( https://rosettacode.org/wiki/Return_multiple_values )
Re: Returning multiple values from functions in C++
#48Earlier quoted context omitted.
Sometimes Lisp can get annoying though. I've used libraries where a function might return 5-6 values and I only need the first and last. I need to bind all of them and then (declare (ignore...)) the useless bits otherwise I get compiler warnings. It's an annoyance, because I always feel the general ethos of Lisp is to eliminate tedious typing and multiple value returns frequently add a lot of cruft.
I agree that Lisp is not always terse, which surprised me at first too. You can abstract many constructs and eradicate redundancy, but at some point, your only chance of being terser is to use reader macros. However, doing so might not be a good idea either. There are libraries out there that provide syntactic sugar for Common Lisp, which is often discarded because (i) they define their own "ghetto" dialect of Lisp (…
(let ((struct (my-get-decoded-time)))
(format t "Year: ~A~%Seconds: ~A" (time-year struct) (time-seconds struct)))
With the original multiple value return, if there were a bug and I were reviewing the code, I'd need to also review get-decoded-time and see what order the values are in. If instead it returned structured data, I could skip that step as the values are clear.Lisp is still my favourite language. I generally rank languages by how much time/code I'm spending managing the language versus managing the problem I want to solve. Lisp is very good for that, very little cruft so it lets you focus directly on the problem at hand.
Re: Returning multiple values from functions in C++
#49Earlier quoted context omitted.
Multiple values are not "just" an optimization hack, they are designed to be convenient to use. I don't know which construct you find "weird". Multiple-value-bind is a descriptive name which is long to type but this does not matter (type m-v-b + auto-complete). Typical example: you read a line in a file. The line you get is terminated either by a newline character or by the end-of file. The implementation of read-lin…
Maybe this is different in CL, but in scheme, if you're using a procedure that returns multiple values, there is no default return, or wrapping the multiple values into a list: You have to use call-with-values, any number of srfis providing sugar, most commonly srfi-8, although 11 and 71 also exist, and without the sugar, god knows how many lambdas. EVERY. SINGLE. TIME. You want to call a function that returns multip…
Re: Returning multiple values from functions in C++
#50Ada has in, out and in/out parameters which adds a little more semantic to C and C++'s pointer parameters. Author mentions Common Lisp's multiple values, and one of the main feature of multiple values is that they are optional: the caller does not need to use secondary values. Even though floor returns 2 values, the following is a valid expression: (+ (floor x) 2) Only the primary value is used. A compiler typically…
Sometimes Lisp can get annoying though. I've used libraries where a function might return 5-6 values and I only need the first and last. I need to bind all of them and then (declare (ignore...)) the useless bits otherwise I get compiler warnings. It's an annoyance, because I always feel the general ethos of Lisp is to eliminate tedious typing and multiple value returns frequently add a lot of cruft.
You need to hack around it. Don't like it? Improve it. Sketch:
(defun make-vars (vars &aux syms)
"creates uninterned symbols for vars named NIL.
Returns a list with those replaced and a list of the new syms."
(values (loop for var in vars
if (eq var NIL)
collect (let ((sym (gensym "ignore"))) (push sym syms) sym)
else collect var)
syms))
(defmacro multiple-value-bind-some (vars form &body body)
"Similar to MULTIPLE-VALUE-BIND, but variables named NIL will be ignored."
(multiple-value-bind (vars syms) (make-vars vars)
`(multiple-value-bind ,vars ,form
(declare (ignore ,@syms))
,@body)))
Example (defun foo (x)
"returns five values"
(values x (* x 2) (* x 3) (* x 4) (* x 5)))
(defun test ()
(multiple-value-bind-some (a nil nil nil b)
(foo 10)
(list a b)))