5 ms·
Even though it doesn't look like it, I could've sworn Prolog was homoiconic. Smalltalk can also do a lot of the cool lisp wizardry. I know Alan Kay (a user on
by 3rdAccount 8y ago
Even though it doesn't look like it, I could've sworn Prolog was homoiconic.
Smalltalk can also do a lot of the cool lisp wizardry. I know Alan Kay (a user on here who was on the team that designed Smalltalk at Xerox-PARC) likes both langs. I've never heard him describe what he thinks are the pros and cons of both though.
You can write a lisp in a few lines of Forth. I've never done it, but people talk about it a lot, so I'm going to assume fact.
- benhoyt 8y ago> You can write a lisp in a few lines of Forth. Seems unlikely. Forth isn't garbage collected, is untyped, etc etc. So you'd have to add those things in "a few lines". Though I guess it depends what you mean by "a few". I was thinking a couple of dozen. Looks like someone's done it in 500 (though without GC -- is that still Lisp?): https://forums.parallax.com/discussion/160027/lisp-technically-scheme-written-in-forth https://forums.parallax.com/discussion/160027/lisp-technical...
- pjmlp 8y agoNot all Lisps had GC in the early days. There were some mainframe implementations that would just allocate until there was no more memory left.
- vidarh 8y agoIn addition to not technically needing a GC, a simple GC can be small if you don't care (much) about performance. One variation over a basic tricolor mark and sweep using linked lists for each "color" is basically (ruby-ish pseudocode): # At this point all objects are in the "white" set. We don't know if they're reachable (in which case they're garbage) # Mark roots push_registers_to_stack stack.each {|ob| grey.append(ob) } # You need to do this to any other roots as well, e.g. any pointers from bss. # Iteratively scan every object, moving unscanned objects into the "grey" set (reachable but unscanned) grey.each {|ob| ob.referenced_objects.each {|ref| grey.append(ref) } # "ob" has now been scanned, so moving it into the black set (reachable *and* scanned) grey.delete(ob) black.append(ob) } # What remains in the "white" set is now the garbage, so free it. You can also, if you want, move this aside and free it lazily. white.each {|ob| ob.free } white = black A "real" implementation of the above can be done in <100 lines in many languages. Doing efficient gc gets more complex very quickly, though. The mruby gc is a good place to see a more realistic tricolor mark and sweep that is also incremental and also includes a generational collection mode. It's about 1830 lines of verbose and well commented C including about 300 lines of test cases and a Ruby extension to interact with it. A simpler one like the above could certainly be much smaller even in C.
- kazinator 8y agoRuby-ish pseudo code is somewhat remote from working Forth.
- vidarh 8y agoIt's remote in that it looks very different, but not in terms of complexity. The operations used in the pseudo code are basically just. - Pushing registers onto the stack - Iterating over the stack - Appending to a linked list - Popping the first entry off a linked list - Iterating over a linked list - Calling a function/method ("free") to release the memory. In it's most naive form this would mean appending it to a linked list of free memory. The two first requires dipping into assembler in a lot of languages. The rest will be tiny in most languages, including Forth, but my Forth knowledge is very rudimentary hence why I didn't try.
- tgvaughan 8y agoThis is actually a random side project of mine! https://github.com/tgvaughan/scheme.forth.jl https://github.com/tgvaughan/scheme.forth.jl
- marcosdumay 8y agoI always have problems with the definition of homoiconicism... Prolog code is represented the same way as data, but (AFAIK) there is no functionality for manipulating code at run-time or interpretation-time. I believe allowing macros is a necessary condition for homoiconicism, if I'm right, then Prolog isn't it.
- 3rdAccount 8y agoNo, I think just code is data is code right? Also, I'm not sure macros are needed for a language which doesn't do compilation.
- carapace 8y ago> there is no functionality for manipulating code at run-time or interpretation-time Sure there is: http://www.swi-prolog.org/pldoc/man?section=manipterm http://www.swi-prolog.org/pldoc/man?section=manipterm Example: ?- foo(Bar, Baz) =.. List. List = [foo, Bar, Baz]. And: ?- F =.. [foo, Bar, Baz]. F = foo(Bar, Baz).
- cjallen88 8y agoYou can do all that with term-rewriting in Prolog, you can use a grammar to parse a file of arbitrary text and transform it into prolog terms to be executed etc