Just saw an announcement about Falcon, a new programming language (via). Reading the documentation, it seems quite reminiscent of Python, or maybe it's just that I'm not getting a wide enough perspective. Anyway, following similar posts on Boo and Prothon, here's the differences with Python that I can see:
The VM is written in C++. This seems to be an important point to the author. I wonder if it is hard to embed in a C application as a result (but that much easier in a C++ application?)
Doesn't use whitespace for blocks (uses end). Does use newlines to separate statements.
One line control structure if you use a colon. E.g.:
if a do stuff end /* equivalent to: */ if a: do stuff
No print statement (it's a function: printl(args)).
/* ... */ and // comments.
Conditional expression (aka ternary operator): expr ? true_value : false_value.
switch structure, like switch; case a; ....
Two for formats. Python's for var in sequence and another BASIC-like for var = start to finish [step amount].
No tuples. [] is optional, kind of how () is optional around tuples in Python. But [item] is unambiguously a single-item list, where (item) is one of Python's weirdnesses (you need (item,)).
I don't think you can iterate over strings. Good call.
Dictionaries look like [key1 => value1, key2 => value2, ...]. Kind of like PHP.
Functions defined with function, not def. Bizarrely, after all these years programming Python, if I spend an hour or two in Javascript and go back to Python, I'll use function instead of def.
Functions can begin with a block of static variables (static; assignments... ; end).
"Stateful" functions are a special case of static variables I guess...? I really don't get this. I feel like you could use generator functions to a similar effect in Python, but it would be idiomatic, not something codified in the language.
Seems to be prototype-based. I don't know exactly why this is popular; it always confuses me, and I feel like classes make a better baseline with prototype extensions. So you define objects with an object keyword.
You have to use self.var just like in Python, but methods don't have a self parameter. I strongly disagree with people who think Python's self.var is a wart, so kudos to Falcon. Like Python, self actually seems to be a parameter, it's just hidden (and null when a function isn't called as a method). So you can do the same kind of reassignment of methods like in Python.
Methods in object blocks aren't introduced with any keyword at all, they are just kind of declared (basically just like a normal function declaration, but without the function). You can also have assignments in the block, like in Python.
Objects can "inherit" from classes by using object <name> from class1, class2, .... I say "inherit" because we don't seem to be using traditional classes.
Has a property operator, so that obj provides method is equivalent to hasattr(obj, "method"). Encourages look before you leap, but also makes duck type checking seem more natural and less hackish.
A has operator, that is basically a bitmask. So you can do obj has 2 to do something like obj.attributes & 2. Making it somewhat less hackish, you can enumerate these attributes. Presumably you cannot use expressions on the right side of has, because the attribute names are locally scoped to the object. There is a fixed 32 bit limit on the attributes. You use give obj attr_name and give obj ! attr_name to set and unset these attributes. Weird.
Ah... now we get to classes. Weird to start with objects and not classes. Anyway, this makes me feel better. Classes look like:
class ClassName(params, ...) from SuperClasses, ... use params here to initialize object function method(): ... end
It's weird to me that the equivalent of Python's __init__ is right in the body, and there's no formal transition to the method list. Classes are called to instantiate them, just like in Python.
Uses try; statements; catch [var]; end for exceptions. The exceptions look wack. Uses integer codes to distinguish exceptions from each other. No way to catch specific exceptions. Not extensible the way Python exceptions are (Python exceptions are full object that can be specialized). Why wouldn't you make a special form to limit what errors you catch?
Variables are explicitly exported, export symbol1, ...
Modules are loaded by path name, like load library/module_name. It's not strings, so the loads can be (more or less) statically determined (like Python imports) -- this is good. Using path syntax gives you a clear distinction between absolute and relative paths, and the meaning thereof. This is good too. Seems to fold together multiple directories (with a path); this isn't so good. I at least like C's distinction of #include <stdio> and #include "mylibrary". It seems to not use namespaces, and just include all the symbols -- very bad!
Has "variable aliasing", so that one variable tracks the changes in another variable. Looks like var_alias = $var. Weird. Also in a function call, $ passes the variable by alias, so that:
function modify(param): param = "new" var = "old" modify($var) var == "new"
Ick. This just enables bad smelling code.
Has constants. That's nice.
Uses include "filename" to textually include another file. Ick!
If you use sender in a method (or function?) you get the object that called you. It's like dynamic scope for the call stack. Ick!
Allows blocks (maybe?) in expressions, at least for lambda:
func = lambda (a, b); return a * b ; end
The syntax feels weird. People keep talking about this in the python list, fantasizing (and it'll never be more than a fantasy) that extended lambdas will happen sometime. The weirdness of the syntax is why I think it's a fantasy. And lambda is a dumb word -- Church's use of the lambda character doesn't make it an intuitive term!
Has coroutines, which are basically cooperative (as opposed to preemptive) threading.
I can't say what Python has that Falcon doesn't (since I don't know Falcon), but it's probably quite a lot. Many parts seem somewhat sloppy -- like load -- and make me think of it more like Tcl or Lua than Python. The author uses the term "scripting language" a lot. I honestly can't figure out what it offers; it doesn't compare itself or justify itself with respect to other languages. Considering its similarity to Python (since there's many more points where they are identical, compared to these points where they differ) it would be nice to see a why-Falcon-instead-of-Python document or something. Actually, I don't know Lua, but if I did I suspect I'd see strong similarities there as well.
If this were a language based on Parrot (if it was ready), or .NET, or the JVM, it could be a plausible language to use. I don't really get it as a standalone language, though -- the investment cost is too high for very little return.
There's a thread of discussion here, though it seems to focus on lambdas, because functional programming obsessives care about lambdas and equivalencies even when most programmers are busy thinking about programming (okay, maybe it's just that I'm tired of Lambda The Ultimate discussions).
Looks very very similar to Lua (www.lua.org).# Jonas Galvez
I think being implemented in C++, this has one of the same problems Prothon had. There are no standard libraries or existing 3rd party libraries that you can use. You can't directly use Python modules, .NET libraries, or Java libraries. You have to start all over. No GUI toolkit, for example. Other languages like Jython, Groovy, IronPython and Boo don't suffer from this problem.
You might also check out LiveLogix. It runs on top of the CPython VM, so you can still use Python modules.
# Carson
Thanks for your reviewing; I am absolutely pleased you found many things in Falcon "kudos"; for the rest, we'll do something before beta ;-).
Some note about Falcon:
Falcon is not meant to build BIG applications out of it. I.e. this is a clear statement in RUBY (a language capable to do small + large apps), and this is also somehow claimed but never quite attained by Python. The target of Falcon is to be fast enough to be a sensible choice over C for some duty, embeddable and powerfull to do small thing quite well. Also, yes, to be C++.
You know there's no problem in linking C in C++; the other way around is often more hacky, and that's was the reason of my choice. Also, I have proof of the fact that C++ compilers provide better optimizations for quite a lot of things. Finally... the api is more clear, and that's important to me.
A couple of precisations: - About try/catch; actually, what you are going to catch is 99% an Error class or subclass item. The fact is that in 99% of the progrmas I noticed that selecting which kind of error have been raised is just a pain. So, if you really need that, you may easily use the switch statement over the error variable to detect it's error type. Remember that you don't have switch in python... so, having a pre-branch has more sense.
However, this is not a (completely) fixed decision. I may introduce a per-type or per-class catch filter later on, but the catch-all catch statement will stay. Also, the Falcon VM provides unstoppable exception, that may not be handled by scripts; they are not present in Python (i.e. you can block a syntax error if you use a catch-all statement), so a catch-all statement as LESS sense in python...
- Functions: static blocks are not just assignmens, but whole code slices done only once. Same for the class static statement: they are executed only when the first object of a class is created.
- Why starting with objects: we are programmers, and we know OOP, but I found in my teaching experience that newbies are better introduced to OOP if you first talk about objects, and then about classes. Also, I always felt the lack of singleton objects in every language I dealt; I used them in some contexts, and I felt quite comfortable with them.
- Attributes can be matched against expressions: they are NOT object or class specific. Once defined, you may assign an attribute to any object in your program. They are meant for EXTREMELY fast passage of data between embedding applications and internal scripts, (apps/scripts can read and set attributes without accessing the object structure and decoding the retreived item) but being a "trasversal" extra-oop thing, they may be useful also in a more general context. They are currently limited to 32, but before beta stage I will use 64bit integers; I am just considering if using them ALONE or continue to use also int32 if the number fits it.
- Stateful functions are an elegant way to implement stateful machines. This also allows to bind every function (or method) with a "state" value, that may be kept inside the function, instead of having to record and use the return value of it.
- Self and Sender objects are special registers of the VM, so they are not held in the stack, and do not weight in calls.
- The load statement is meant to provide a "logical" module loading capacity. The command line, that is, a minimal embedding application, will just load all that the script requires. More sophisticate embedders (i.e. your app), may filter out easily load requests and provide other things instead. Also, the embedder may provide its own function, objects and classes to the scripts, without having them to load any "application specific module". Falcon wants to be your application configuration language...
- In Falcon you can change the behavior of object and classes on the fly. I.e., instead of having a method to check if some condition exists and then act accordingly, you can just change the method depending on the condition.
Falcon is alpha. It may change a lot before beta, but I am currently quite satisfied with it now; I am just making module serialization more clever and much smarter object data access, but for the rest I am really happy with it. For the ppl that was lamenting lack of GUI, I will add an embedded AWT (abstract windowing toolking), something like the Java one but more focused on GTK concepts (that is, intelligent placement instead of fixed one, unless otherwise specified). So we'll have an AWT and many DRIVERS that will provide the AWT with real output.
Bests, Gian.
Oh, I forgot. About namespaces, I don't think they are necessary in untyped languages, especially not namespaces a-la-python. A very similar thing may be easily implemented by exporting a singleton object with the same name of the module, if the need arises.