Live data from Hacker News

Ale – A Lisp Environment Written in Go

ale-lang.org

31–40 of 44 posts

Re: Ale – A Lisp Environment Written in Go

#31

Earlier quoted context omitted.

Lisp-2 is intuitive to those who know shell. foo() { echo hi } $ foo=1 $ foo hi $ echo $foo 1 $ var=$(foo) $ echo $var hi $ var=$foo echo $var 1 Separate space for variables and functions/commands. Hardly anyone bats an eyelash about this. This provides a hygiene benefit similar to what we have in a Lisp-2. Specifically, suppose we do this: $ ls=abc by doing that, we have not shadowed the ls command. We can name shel…

Exactly this. When I write Scheme code, it trips me up when I have to re-spell variable names to avoid clashes. Experienced Scheme programmers don't find this difficult; they think it's weird to have to use funcall. It's just a function of what you're more used to.

It happens in C, when you have short function names. In the C internals of TXR, I have to be careful about using variable names like list or cons, because then those functions are not available.

A certain list accumulating macro calls the tail function. If I accidentally introduce a variable called tail where this macro is used, oops!

In typical C code, you're protected from clashes by using short variable names, and long function names.

Re: Ale – A Lisp Environment Written in Go

#32

Earlier quoted context omitted.

I'm new to LISPs. What's the difference between LISP-1 and LISP-2?

I believe it has to do with namespaces for naming functions vs variables. A lisp-1 has one namespace that encompasses variables and functions. In a lisp-2 they are separate and so it is possible to have a variable with the same name as a function.

The nice thing in Lisp-2 is that Lisp code is not only made out of function calls, but also special operators.

In a Lisp-1, simple variable bindings can shadow special operators. If you name a variable let, you're locked out of further let binding in that scope. That is ugly. Yet, you can hardly prevent let being used as a variable name. In a Lisp-2, we don't have this problem. We have a more benign version of it, rather: what happens if someone names a function let. That can be dealt with by a compiler warning or error. E.g. our implementation can warn that a special operator is redefined. And then it can cheerfully ignore the redefinition, so that let continues to work.

Then there is the question, in a Lisp-1, given that we have a let operator, and operators and variables are in the same space, what the heck is the value of let as a variable? What should (let ((let let)) let) return? This is hand-waved away with something lame like let having an undefined value or whatever.

This is ugly and points at Lisp-1 not being as clean and consistent as it is cracked up to be.

With macros, it's possible for the same symbol to have both a function and macro binding! In a Lisp-2, that's like 2.5 namespaces.

  This is the TXR Lisp interactive listener of TXR 219.
  Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet.
  1> (defun foo (arg) (* 10 arg))
  foo
  2> (defmacro foo (arg) ^'(multiply ,arg by 10))
  foo
  3> (foo 15)
  (multiply 15 by 10)
  4> (mapcar 'foo '(1 2 3))
  (10 20 30)
  5> (fboundp 'foo)
  t
  6> (mboundp 'foo)
  t
  7> (mmakunbound 'foo)
  foo
  8> (mboundp 'foo)
  nil
  9> (foo 10)
  100
It is said glibly that Lisp-1 dialects uniformly evaluate all positions of a form, rather than treating the leftmost one specially. But that is actually not true. A Lisp-1 dialect, just like Lisp-2, looks at the first position and treats the expression specially if there is a special operator or macro there! (But: not if it's a symbol macro; yet, symbol macros and macros end up in the same namespace.)

Moreover, after a function call form like (f x y) is evaluated (uniformly, to be sure), the semantics isn't uniform: the first value denotes a function (or other callable object), and the remaining values denote arguments to be applied to it. That's a fundamental asymmetry, shared with Lisp-2. Why fret about symmetry in the evaluation, when the semantics of the application itself is ultimately asymmetric.

In the end it just boils down to the pragmatics: hygiene considerations versus not having to use funcall for working with higher order functions.

Re: Ale – A Lisp Environment Written in Go

#33
post #28
post #25

Earlier quoted context omitted.

Nah man,macros are the bee's knees! Being able to add new constructs to a language is neat. My favourite examples are match.scm - a pattern matcher that produces zero overhead code - and racket's for loops, which are just regular macros. Being able to add features like that is amazing. Clojure'sarrow syntax? No problem. Python's list comprehensions? Can be done! A library for Pattern matching? Many to chose from! Pat…

Unpopular opinion that doesn't even disagree with you. LOOP is superior to rackets for loops. The minimizing and maximizing constructs are surprisingly readable.

I agree to some extent. To get the same power from rackets loops you have to do a lot more work using for/fold.

I have an implementation of rackets loops for guile scheme, and I'm currently rewriting it to allow arbitrary transformations in the loop clauses.

Say I want to write a Fibonacci loop, currently I can't do this:

    (for/list ((a :first 0 :then b) (b :first 1 :then (+ a b))) a)

Re: Ale – A Lisp Environment Written in Go

#34
post #8

I believe every new LISP author should begin their presentation with how does their language compare to other LISPs (CommonLisp, Racket and Clojure in particular). Mentioning it's a LISP-1 in the beginning is nice but not really enough.

I agree, though they did put some of the first-questions-that-come-to-mind on the second page, " https://www.ale-lang.org/intro/" : > What is Ale? > Ale is a Lisp-1. In this way it is more like Scheme than like Common Lisp. Unlike many Lisps, Ale does not support both interpreted and compiled operation. Instead, when the programmer performs an (eval), Ale immediately compiles the form and invokes its virtual machine.…

https://twitter.com/kode4food/status/1137335122330566657

Re: Ale – A Lisp Environment Written in Go

#35

Earlier quoted context omitted.

Common Lisp is a Lisp-2; Scheme is a Lisp-1. Lisp-2 is handier [to me] in many ways but it requires an inelegant syntax when you want to evaluate a function that returns a function and then call said returned function. Assume you have a function foo that when called returns the function '+. To then call that function with args 1 & 2 you'd say in a Lisp-1: ((foo) 1 2) ; 3 while in a Lisp-2 you'd have to say: (funcall…

In what ways is it handier? I've never heard of benefits of Lisp-2. Whereas Lisp-1 is more intuitive to those who know JavaScript/Lua/etc.

If you're doing anything involving externally defined/named data and analysis, working with it interactively/exploratory, I find it infinitely better, just because you can BOTH represent data using the same name that external sources are using AND not clobber/shadow any functions, macros or code currently in scope.

Its a little thing, but if I designed a language for data munging/science/analysis, it would be a lisp-2...

/and yes, i'm well aware that python and julia are not...

Re: Ale – A Lisp Environment Written in Go

#36
post #22
post #13

Earlier quoted context omitted.

Not sure if that's a good example. My lists of foos are usually named "foos", not "list" or "lst".

I come from a scheme tradition where higher order functions are used for many things. I often use the name lst for generic lists. I am not so sure I think it matters. In the place where it matters the most (macros) scheme has macro hygiene. That discussion is not worth having here though, because it is really just a matter of taste. I like both ways, but prefer the scheme way where you have to explicitly break hygien…

Now that I think of it, I certainly have tripped on "list" arguments in Python, but adopted haskellers' "xs" for such generic uses and forgot about it. BTW, GHC throws especially funny messages when you define a variable like "head" or "last" and then try to call the shadowed function. OTOH, Emacs' python-mode highlights builtins regardless of context, very convenient to catch such lapses immediately.

Re: Ale – A Lisp Environment Written in Go

#37
post #8

Earlier quoted context omitted.

I agree, though they did put some of the first-questions-that-come-to-mind on the second page, " https://www.ale-lang.org/intro/" : > What is Ale? > Ale is a Lisp-1. In this way it is more like Scheme than like Common Lisp. Unlike many Lisps, Ale does not support both interpreted and compiled operation. Instead, when the programmer performs an (eval), Ale immediately compiles the form and invokes its virtual machine.…

https://twitter.com/kode4food/status/1137335122330566657

Excellent. You might also like R5RS or R7RS, plus `syntax-case` (though `syntax-rules` is very nice, when the problem fits it). For work that builds upon Scheme's syntax extension mechanisms, see Racket for ideas, including its syntax objects, very powerful `syntax-parse`, a very simple template-based syntax transformer, and the `#lang` feature.

Re: Ale – A Lisp Environment Written in Go

#39
post #4

I think this has a lot of potential if it's able to call Go functions, like Clojure can call Java functions. The language would have a healthy ecosystem of libraries to boot.

It's weird to me that there aren't more compile-to-Go languages. The ecosystem of Go packages is great, and the runtime is undergoing continuous refinement by a team of really smart people.

Probably because go is dogshit and slow
Post reply on HN