lainchan / λ
ITT we share our ideas, misery and favorite features
byte · 2022-06-23 14:16
Programming Languages:
Let's share some of the things you like a lot in a particular language(-s) and want to see in others. Ideas, stuff you struggle with and what this stuff could be replaced with
Drifter · 2022-06-23 14:31
>>31594
Go's Channels and goroutines.
Sure, channels are easy enough to implement in C/C++, but I shouldn't have to do it.
Goroutines are likewise easy to use, and I don't have to worry about manually setting up workers to do simple tasks.
I also can't wait for fetch() to get added to Node. It's already available in the latest as an experimental feature, but it's coming to standard node soon. I love not needing to worry about the details and just getting the data (or a descriptive error) from a convenient builtin.
I also like the way C++ closures let you exactly define which variables are pulled into the function's internal context and whether it's by copy or reference. JS arrow functions are great and fast and all, but we all know the pain of realizing you used an async function inside a closure in a loop and some loop variable changed on you. That can be a feature, sure, but it's such an esoteric cause of error.
nibble · 2022-06-23 17:07
Pick from http://random-state.net/features-of-common-lisp.html
Some I really miss in C++ (job) that aren't tied to Lisp's homoiconicity or dynamism (like macros with limitless power): sane numerical tower with multiprecision integers and rationals, named/keyword arguments, multidimensional arrays, loop/iterate, runtime compilation, user defined streams.
I do miss parametric typing and some lower level features in CL, though. And from Tcl: inline list expansion via {*} (see example next), builtin event loop.
Argument list splicing examples:
lisp
;; -supplied needed to avoid double evaluation of arg without using once-only
(defmacro mac (fun &optional (arg nil arg-supplied?))
`(funcall ,fun ,@(when arg-supplied? (list arg))))
(defun fun (fun &optional arg)
(apply fun `(,@(when arg (list arg)))))
CL-USER> (mac #'+)
0 (0 bits, #x0, #o0, #b0)
CL-USER> (mac #'+ 3)
3 (2 bits, #x3, #o3, #b11)
CL-USER> (fun #'+)
0 (0 bits, #x0, #o0, #b0)
CL-USER> (fun #'+ 3)
3 (2 bits, #x3, #o3, #b11)
vs
tcl
[~] proc p {fun {arg {}}} {{*}$fun {*}$arg}
[~] p + 1
1
[~] p +
Nanashi No Gombe · 2022-06-24 01:33
>>31598
>-supplied needed to avoid double evaluation of arg without using once-only
You'd test for the form at macroexpansion time, not the value it evaluates to at runtime, so there would be no double evaluation with something like `(funcall ,fun ,@(when arg (list arg))) , no? But then you wouldn't accept a literal NIL, which is a perfectly legitimate argument to a function, so -supplied is still the right thing, but for a different reason (and FUN would be the wrong one).
I am making an off-topic post arguing about a trivial choice with no bearing on what is being demonstrated on a 4 line example, yes.
progn · 2022-06-24 04:15
>>31601
Huh, you're right and I'm dumb. Even had to test to make sure (for my defense, it's 6AM here).
Spike Spiegel · 2022-06-25 18:21
I don't speak Scala, but it has the best idea about function literals.
Function literals tend to be hard to read for two reasons. One of them is syntax: Ruby's { |a| a == 4 } * looks quite compact, but all that punctuation slows down the eye. Haskell does quite well at \a -> a == 4 - that is, once you learn not to read the backslash as an escape character. Scala is already top of the class with a => a == 4 , but it has something else which is an order of magnitude better.
The other reason why function literals are hard to read is that you have to perform parameter substitution in your head. Partial application can help here: you can't get much clearer than (== 4) . But if the type of the missing argument is not immediately obvious from the function's name, you have to run type inference on the context to figure out what's going on; and if the function doesn't take its arguments in the order you need, you have to write a wrapper, or dick around with flip (don't).
What Scala does is solve both problems at the same time, by getting rid of the parameter declaration:
list.exists(_ == 4)
In Scala, any expression that has the special identifier '_' in it is translated into a function, with the underscore being replaced with the argument. Sadly, things get hairy if your function takes several arguments [1]:
>The rules for using "_" is that the first-time use of "_" refers to the first argument, the second-time use of "_" refers to the second argument, and so on.
Ouch! Readability flies out the window when several arguments are involved, but it's still a net gain overall.
* Yes, I know that's not technically a procedure in Ruby, but a block.
[1] https://en.wikibooks.org/wiki/Scala/Function_literals
Terzibashjian · 2022-06-25 21:45
>>31610
Unless I've misunderstood your point, nothing prevents you from using parameters names (manually or via a suitable macro doing summary code walking to deduce the number of arguments) that work around this "problem".
Something like
(defmacro λ (&rest args) ...) ; if args is of size 2, it's a normal lambda, otherwise (size 1), use the "automatic positional argument naming" scheme
(λ (= _ 4)) ; equivalent to (λ (= _1 4))
(λ (= _1 _2))
(λ (a b) (= a b))
But to be honest, except the keyword "lambda" being long (hence the λ) compared to these terse (but needing specialized syntax) examples, I've never felt this was a problem.
Only in C++ where you need return and the mandatory semicolon do I feel a bit dirty.
J.C. Denton · 2022-06-26 18:08
>>31615
Nothing will prevent me from building this into the languages that I design in the future, rest assured. My point, if anything, was that nothing prevents the designers and maintainers of other languages (that don't have homoiconicity + macros) from adding it to theirs, either. Forgive me for not finding a more suitable place to post this than the thread about features you wish other languages had.
However, having thought about the problem further, I take back my claim. Parameter substitution is only costly to do when there are several parameters, because you have to keep checking which order they're expected in and matching that to what the surrounding code will do - and that's precisely the case where Scala's syntax breaks down. It's a great space saver, but I'm no longer convinced it improves readability in any of the cases that actually need it.