6 ms·
I strongly believe concatenative languages – particularly statically typed ones – are one paradigm of programming that have not been explored nearly enough. It'
by simplify 10y ago
I strongly believe concatenative languages – particularly statically typed ones – are one paradigm of programming that have not been explored nearly enough. It's good to see more activity in this area :)
Here's another interesting concatenative language in development that I'm following: http://kittenlang.org/ http://kittenlang.org/
- chubot 10y agoI dunno, it feels like Factor kind of exhausted it several years ago? I think the problem is that concatenative programming is super elegant for some things, and then falls on its face for others. In particular the object/class system of Factor was baffling to me. The paradigms just don't fit together well. I also think Lisp has an awkward object system(s). If you want that paradigm, I think a dedicated language is better.
- aidenn0 10y agoSomewhat OT, but I'm curious what you think is awkward about CLOS?
- cronjobber 10y agoSimple member access like object.foo.bar is apt to read more like this: (class2-bar-of (class1-foo-of object))
- junke 10y agoWhy not use simpler names? (bar (foo object)) I mean, I understand that "a.foo" (class A) does not represent the same name as "b.foo" (class B) due to scoping rules, and so logically you would have to use (a-foo a) and (b-foo b) if you wanted to replicate the same in CLOS. But on the other hand, FOO can be generic and applied to different types of objects. You might even have a mixin providing the FOO slot, which classes A and B inherit from. I find the notation fine, it looks like regular function application (some people prefer threading macros, I personally don't care). Note also that CLOS allows you to add code "between the dots" by specializing accessors on qualifiers (:before, :after, :around), which can be useful to add orthogonal things like logging, persistency, ...
- cronjobber 10y agoThat could work within a single, well coordinated project. Beyond that, the Common Lisp package system doesn't cooperate the way you'd like it to, so you're back at (libraryA:bar (libraryB:foo object)) Since the package system is not hierarchical and doesn't allow local aliases, if you're unlucky you get fully qualified Java-convention package names and end up writing: (com.myfavoritecorp.dept1a.project7.subprojectX:bar (com.biggercorp.dept32.project2.subprojectE:foo object)
- junke 10y ago> Beyond that, [it] doesn't cooperate the way you'd like it to I know what I would like it to do. There are some additional features that people would like to use (https://github.com/fare/package-renaming https://github.com/fare/package-renaming), but even though the package system could be improved, I don't think it is so bad right know. It can be frustrating to try to use it in a way it wasn't designed. I seldom use qualified symbols, so it is generally "(bar (foo x))" anyway. The case when fully qualifiable symbols might be the best solution is when you need symbols with the same name from different packages at the same time (without shadowing), which is quite rare IMO. Also, defining short packages as a facade for other packages is possible. When you develop an application, not a library, you can also choose to mess things up by renaming packages and adding nicknames. By using unqualified packages, I can change the meaning of the code by editing only the package definitions (and recompiling): you code says `(foo x)` and originally meant `(a:foo x)`, but then you change a package and now it means `(b:foo x)`. For example `b:foo` could be a wrapper around `a:foo`. Packages prefix help a little when trying to understand where a symbol comes from. For example, "json:decode" is a little easier to read than "decode". However, with the right editor (or just the REPL) you point to the symbol and have the information.
- zeveb 10y ago> Beyond that, the Common Lisp package system doesn't cooperate the way you'd like it to I'm pretty sure that it is, and that generally in my package I would import bar from libraryA & foo from libraryB and not have to qualify the names. It's only in the case that both packages export a symbol with the same name that one is forced to disambiguate. I'd say that Lisp's package system is very close to perfect — it really does work well.
- lispm 10y agoOne thing one could do is thinking of object.foo.bar similar as 1+2+3 The later would be (+ 1 2 3) in Lisp. Thus slot access could be written as: (? object foo bar) All we need would be a macro ?, which is easy. Alternatively we can write a reader macro such that we can write: #?object.foo.bar The problem with short names and possible package prefixes remains: (? w1 ws:panes ws:background-color color:name) vs. #?w1.ws:panes.ws:background-color.color:name vs. (color:name (ws:back-ground-color (ws:panes w1)))
- aidenn0 10y agoSee my other comment; keywords allow for short names and there is no concern about GF collisions if methods are namespaced to the class anyways.
- kazinator 10y agoYes, there is a concern about collisions when methods are namespaced to classes using non-packaged identifiers. Collisions occur under inheritance. Example: you would like to add a member foo to a base class. The class is widely derived in lots of code, not all of which you even have access to, which might be injecting its own foo. C++ partially deals with this with hacks, like derived identifiers shadowing base class ones (which is totally non-OOP and breaks for virtual functions, which cannot be non-OOP by their nature). C++ partialy deals with the virtual function issue by treating the type signature as part of the name, so that foo(int) and foo(widget&) are different virtuals. Collisions could be a problem even if there is just one class, but its contents are controlled by several parties. Every group has to watch out that they aren't reusing any other group's symbols in that class. Any sort of automatic mechanism which can inject symbols into a class (e.g. in support of aspect-oriented programming or whatever) will run into a clash, unless it uses gensyms, which is inconvenient if the intent is to inject names that are to be publicly known and referenced.
- codr4life 10y agoEven though Factor is based on Forth, that's about where the similarities end. Factor was designed from the start as a stand-alone general purpose language, which is not what I'm looking for here; I'm fine with Lisp as a foundation. Object systems crammed into Forth will always be baffling, the fact that it's doable doesn't make it a good idea. I don't really buy into OOP at all; but i strongly prefer CLOS to alternatives, including Smalltalk; as it let's me reuse pieces of functionality without dealing with the rest. Using a fundamentalist language as a foundation will always come back to bite you from my experience. I prefer my foundations as general purpose as possible, which usually means C or Common Lisp.