Nick Smith
02/17/2021, 2:14 AMlet f = x * x
(note the absence of a parameter list) and then later write let x = 3; let y = f
, which sets y to 9.
It's important for the substitution to be lazy, since this retains the semantics of traditional functions, including the ability to make recursive definitions. Given this, I don't believe I'm re-inventing macros, though I welcome enlightenment.
You can combine this with the usual nested syntactic scoping rules, so it's definitely not the same as using global variables, or the same as closures (where all the free variables are bound at the definition site). The only practical difference seems to be the UX, and the biggest UX downside is probably readability (which invocations consume which values?), but I'm confident an IDE can make the data flow more explicit.
Advantages of this approach:
• Certain programs can become much more concise. For example, in drawing code, you can set the drawing color
just once, and it will be automatically consumed by all drawing functions (i.e. expressions-with-free-variables) that are invoked in that scope. This actually obviates the "type classes" feature that functional languages often pursue. (Type classes aim to enable exactly this kind of "implicit argument passing", but achieve it in a more convoluted way.)
• You've removed the concept of a "function call" entirely from the language. You only need substitution (i.e. referencing). Less features is better, when all else is equal.
Disadvantages of this approach:
• As mentioned earlier, it may be harder to understand which values are being consumed where. But I'm confident that an IDE can make this clear. (I'm building a language based on ASTs and structured editing anyway, so it's guaranteed to be combined with a sufficiently-smart IDE.)
• You need to worry about "accidental variable capture", where a variable which just happens to be in scope is accidentally used by a function (i.e. expression) invocation. I think this is a real problem in languages where variables are identified by text strings, but FWIW, the language I'm designing is not based on text strings, and so can be designed in such a way that a local variable will never accidentally have the same UUID as a free variable found in a function (i.e. expression). In an AST-based language, every function definition should by default use unique UUIDs for its free variables. Only related functions from the same library should share UUIDs, for example the color
variable used in a drawing library should be the same across all drawing functions.
I'd love to hear others' thoughts. Has this been tried before? Are there additional advantages or disadvantages that I've missed? Is it worth a try? Note that I'm thinking specifically about declarative languages here. Imperative languages may add complications (but may not!).Kartik Agaram
Nick Smith
02/17/2021, 2:29 AMKartik Agaram
ibdknox
02/17/2021, 2:42 AMibdknox
02/17/2021, 2:43 AMVijay Chakravarthy
02/17/2021, 2:46 AMVijay Chakravarthy
02/17/2021, 2:48 AMNick Smith
02/17/2021, 2:53 AMx*x == y*y
? Equality of functions is already undefined in most programming languages.Nick Smith
02/17/2021, 2:54 AMNick Smith
02/17/2021, 2:56 AMlet x = z; let y = z
if you want a set of functions to all use the same variable name, post-hoc.Kartik Agaram
f
you have to have a variable called x
. But now say you have another function that needs y
for the same variable. Or x
for a different variable.
None of this is insurmountable, but might add noise.Nick Smith
02/17/2021, 2:58 AMKartik Agaram
Kartik Agaram
Will
02/17/2021, 3:12 AM(defun f () (* x x))
(let ((x 2))
(cl-assert (= (f) 4)))
See Richard Stallman’s paper about emacs on why dynamic scoping promotes modularity: https://www.gnu.org/software/emacs/emacs-paper.html#SEC17Will
02/17/2021, 3:13 AMNick Smith
02/17/2021, 3:22 AMGeorge
02/17/2021, 3:30 AMGeorge
02/17/2021, 3:31 AMfor i in ...:
for j in ...:
# eval a function that expects an index to be assigned to i but you want it use j.
Nick Smith
02/17/2021, 3:36 AMwtaysom
02/17/2021, 6:39 AMNick Smith
02/17/2021, 6:50 AMKonrad Hinsen
02/17/2021, 6:53 AMKonrad Hinsen
02/17/2021, 6:53 AMAndrew F
02/17/2021, 7:19 AMNick Smith
02/17/2021, 7:34 AMKonrad Hinsen
02/17/2021, 8:03 AMNick Smith
02/17/2021, 8:24 AMBrent
02/17/2021, 8:32 AMimplicit
s in Scala? It allows code quite similar to the example let y = f
if f
or its parameter is marked as implicit
. implicit
can be used at the value and at the type level. At the value level - they are mostly used to reduce boilerplate; for example; passing around a db connection throughout the callstack could be done by marking it as an implicit parameter; and then not having to explicitly pass it on a function invocation.
At the type level - it is used to support a number of the advanced Scala language features.
I would say its a very actively used feature of the language. Scala has a new major release coming in which a number of the lessons learned from Scala 2 are being used to refine some areas of the language design and implicts
are getting quite a bit of a rework; so could be an interesting case study.Nick Smith
02/17/2021, 8:37 AMNick Smith
02/17/2021, 8:44 AMBrent
02/17/2021, 8:44 AMNick Smith
02/17/2021, 8:45 AMBrent
02/17/2021, 8:51 AMMiles Sabin
02/17/2021, 11:36 AMMiles Sabin
02/17/2021, 11:36 AMMiles Sabin
02/17/2021, 11:41 AMJack Rusher
02/17/2021, 1:58 PMMiles Sabin
02/17/2021, 2:46 PMNick Smith
02/18/2021, 12:47 AMNick Smith
02/20/2021, 12:50 AMGarth Goldwater
02/20/2021, 2:03 AMNick Smith
02/20/2021, 2:04 AMNick Smith
02/20/2021, 2:08 AMGarth Goldwater
02/20/2021, 2:11 AMGarth Goldwater
02/20/2021, 2:15 AMNick Smith
02/20/2021, 2:19 AMNick Smith
02/20/2021, 2:19 AMNick Smith
02/20/2021, 2:54 AMNick Smith
02/20/2021, 2:55 AMfoo
would only look for x
on the stack if it wasn't found at the definition site. So if you delete the first line, foo
would print "2". This brings you closer to Scala's implicits than dynamic scoping, but it's still different, as I described a few posts up.Andrew F
02/20/2021, 4:57 AMNick Smith
02/20/2021, 5:02 AMNick Smith
02/20/2021, 5:04 AMBrent
02/22/2021, 8:15 AMNick Smith
02/22/2021, 8:23 AM