3 ms·
LFMs and LFSPs (Michael Vanier via PG)
A recent post by PG re: Arc spurred me to Google the term LFSP. Surprise, surprise, PG has an article on it on his own site.
- brlewis 19y agoI think Joe Average and Joe Boss's perceptions of the advantages of LFMs are completely bogus. The same solution implemented in an LFM and an LFSP will be more readable in the LFSP.
- aston 19y agoOne of the features of LFSP's is that the code density is higher, which I'd argue is a good way to make the code harder to read, not easier. Here's an example in ruby: (1...10).each{ |x| print x } Tell me, does the 10 print or not? You'll need a second glance plus a good memory to answer that question. Here's the same code in C++: for (int x = 1; x < 10; x++) cout << x; Verbosity makes it easier for the non-you programmer to look at a random piece of code and decipher it. You feel smarter for having written that Ruby code (and the C++ is boring, I'll agree). But I'm gonna have to say the Ruby code has less readability outright just because it's so dense.
- brlewis 19y agoThe only reason I can think of why someone would look at the Ruby code and not be immediately sure that the 10 prints, is if they've become very accustomed to for loops like the one in the C++ example. It's conditioning, not intelligence, that makes the difference.
- aston 19y agoI think you missed part of my point, which is that "..." vs. ".." is a subtlety introduced by the mantra of high-density syntax seen in LFSP design. The 10 doesn't print, btw.
- brlewis 19y agoI don't think the ".." vs "..." level of density is universal in LFSP design. Macros in Lisp/Scheme are words. See the sql-repeat macro with group-beginning? and group-ending? for example. It makes things more transparent than your typical LFM implementation would: http://brl.codesimply.net/brl_4.html#SEC31 http://brl.codesimply.net/brl_4.html#SEC31
- jey 19y agoThen by your measure, is Perl the most-LFSP language out there? I think Perl reads like line noise. High-density syntax with clear, simple concepts is a desirable feature in a language. Assigning some function to every possible permutation of symbols (a la Perl) is just stupid. Ruby falls into the "just stupid" bin in this case.
- acgourley 19y agoI agree, the for loop is not intuitive at all, just historically present. However, try comparing the ruby against: for x in range(10): print x
- tuukkah 19y agoRuby and C++ both have a complex syntax, nevermind that being superficial. The LFSP example in the article was Ocaml, which doesn't even have operator overloading! What makes Ocaml an LFSP - the little I know about it - includes a nice combination of FP and OO plus a powerful type system.
- pg 19y agoIf (1...10) doesn't yield a list of numbers from 1 to 10 inclusive, that's a bug in Ruby. The problem is not density. It's perfectly clear what this code example should mean.
- aston 19y agoI'm not claiming that that example is dense code in and of itself, merely that encoding important differences in subtle ways is a by product of the LSFP way of thought. Verbose code is the opposite of clever code, so far as I can see.
- jey 19y agoSadly, no: irb(main):001:0> (1..10).max => 10 irb(main):002:0> (1...10).max => 9 Ruby suffers from a bit of Perl-syndrome, and relies too much on magic syntax and "conventions" created by library authors. It's a nice language and all, but I still prefer Python over Ruby since Python is a simple, clean and elegant language with just a small number of elegant concepts.
- gyro_robo 19y agoPython does the same thing with range: >>> range(1,10) [1, 2, 3, 4, 5, 6, 7, 8, 9] Leaving out the starting value starts at zero: >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Which is like dotimes: [1]> (dotimes (i 10) (format t "~d" i)) 0123456789 NIL There's an implied "less than the supplied high value" in all cases.
- pg 19y agoActually Vanier may have a point that LFMs make programmers more interchangeable at big cos. So ultimately the argument against them may be startups.
- brlewis 19y agoHaving a language that is massively popular is one factor in making it easier to find someone to take over code, but I think many managers have an unrealistic estimate of how much it helps. In some ways it actually hinders, by putting more noise into the hiring process. In my day job, the ultimate argument was hiring a new graduate who was writing good production code in the LFSP on his second day. An LFSP lets you create a language that fits the problem domain nicely. This works both in normal companies and in startups. If you're saying that startups can prove the value of an LFSP by being successful with it, I agree. If you're saying that doing a project as a startup eliminates the risk of having code that is hard for someone else to maintain, then I disagree. There are plenty of reasons why a startup might need to find someone capable of working within their codebase.
- tuukkah 19y agoTo get wider use of LFSPs, it would be important for more people to learn that you can and it's completely reasonable to interface several programming languages. You need to be comfortable with both languages to work on the interface, but I find it surprising we didn't practice this at school at all. To explicate what the article touches: Perhaps you really have to use Java because of platform or workforce requirements, but it doesn't mean you have to use 100% Java. More experienced developers can build some of the low-level classes using C++ via JNI. They can also set up BeanShell or Jython for user interface and test scripters.
- nostrademons 19y agoUnfortunately, interfacing multiple languages is itself not a strategy for LFM-people, because most of them can (or believe they can) only fit one language into their brains. There are costs to using more than one language on a project. Managers frequently overestimate these costs, because they're the ones who will look bad if their superior (or investor) looks at their development process and say "Wow, this is chaos. No wonder you can't ship software." There does seem to be a loophole: you can use multiple languages if they all start with the same buzzword. So, the same manager who balks at a Python/C++/SQL solution because it uses too many languages has no problem requiring that his developers learn Java, JavaScript, Java Server Faces, Java Persistence Query Language, Java Expression Language, and the Java Standard Tag Library, because they all start with "Java". Same goes with XML/XSLT/XSLFO/XPath and derivatives. Based on this observation, I suggest a renaming of all common hacker tools. Python should be renamed "ParrotSnake", Ruby "ParrotGems", Lisp "ParrotParens", SQL "ParrotQueries", JavaScript "Parrot in a Browser", HTML "ParrotTags", Haskell "ParrotMonads", and so on. Then we could freely use any of these on a project, because they're all the same language, duh. Of course, the Parrot project itself should be canceled, because it'd defeat the purpose to have them actually running on a common VM. This is strictly a marketing initiative.
- tuukkah 19y agoInsightful! But does this in your opinion apply only to LFM-people - my understanding is most LFSP-people don't see multiple languages as an option either?
- pg 19y agoI'd forgotten how well written that was. It's better than 99% of the essays on the web. And yet it was just an ordinary email, not intended for publication.
- mynameishere 19y agofor (i = 0; i < N; i++) Odd example to use. It's always annoying to re-type the same thing over and over. But I recently went through a mountain of my Java code and replaced: for (Object obj : list) with int size=list.size(); for (int index=0;index<size;index++) I'm definitely very long suffering! It took a few hours but what you get with abstractions is a loss of control over implementation. When you use the tighter loop, the compiler turns everything (roughly) into this: Iterator it=list.iterator(); //Which calls new ListItr(); for (it.hasNext()) { Object next=it.next(); The abstraction has to do that because it doesn't know whether the list (really, the java.util.Collection) is a LinkedList or an ArrayList or a Set. If your loop itself is in a tight loop, it isn't hard to call it millions and millions of times during program execution--which makes millions and millions of unnecessary allocations and method calls. There is a loss of performance which, at the end of the day, is more important than how much you enjoy your job. Of course, other languages would allow you to specify an implementation for a given abstraction.
- abstractbill 19y agoThe replacements were for performance reasons, and it took a few hours to do. Sounds like it might been more productive to replace only the occurrences the profiler told you were causing problems...
- deleted 19y ago[deleted]
- pg 19y agoSounds like a case for macros.
- tuukkah 19y agoA higher-order method 'iterate' on containers would also do, and it would be more idiomatic in the languages i know.
- Tichy 19y agoI don't understand: if you are sure that it is an ArrayList, why don't you use ArrayList instead of List to begin with? If you are not sure that it is an ArrayList, then you shouldn't use the for(int i = 0...) loop, because accessing each list element in a LinkedList by index would be extremely slow. As for typing, in Eclipse you just type "for"+CTRL+Space and it completes the for loop for you.
- marketer 19y agoI'd be careful with pure research languages like ocaml. It has some advanced features (polymorphic variants, functors, camlp4, etc. ) that even smart people have a hard time understanding, because they are probably the subject of someone's phd thesis. Also, LFSP's can be quirky: in Ocaml, for instance, native integers are only 31 bits (using 32 bits requires the Int32 module, which requires its own set of operations to use. Don't you love static type checking?) Bugs in LFSP compilers probably appear much more often compared to LFM compilers.
- tuukkah 19y agoDo we admit that smart people aren't infinitely smart? With LFSPs, I often get the feeling I'm too stupid for a language, but in many ways it's better than often feeling the language is too stupid for me. Who cares whether you got 31 or 32 bits? The different operator names are because Ocaml doesn't have operator overloading. For statically type-checked and "overloaded" operators and functions, see type classes in Haskell.
- bsaunder 19y agoFor most of the article, I kept thinking, why hasn't he tried SWIG (http://www.swig.org http://www.swig.org). Keep the needs-to-be-fast stuff in C/C++ (hopefully with a well designed API), and code the fun, flexible, interactive stuff in the LFSP of your choice (sorry apparently not all LFSP supported).
- bayareaguy 19y agoPerfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. - Antoine de Saint-Exupery
- cheponis 19y agoI think this is why all TRUE wizards write in Assembly Language.
- uuilly 19y agoI totally understand people's complaints about C++. However I am never sure if they are aware of some libraries that may concerns: boost::function allows you to easily interchange function pointers, memeber function pointers and function objects. boost::lamda allows you to define transient functions at the call site. This makes the old STL way more useful. To be sure the syntax can be a bit funky... boost::bind pulls all the fun of boost::lamda and boost::function together. With only the tiniest bit of discipline boost::shared_ptr's mean you never have to worry about memory management again. boost::any and QVariants (from the Qt Libraries) help you manage dynamic typing. So an array of boost::any's can hold int's, char's, string's and AnyTypeYouWant's all at the same time. Everything I've mentioned is either in the standard or will be soon. Really undergrad C++ is only the beginning. The STL and boost are almost a language unto themseleves. I never use raw arrays or naked pointers anymore and it's made development WAY faster while maintaining performance. PG asked, why use a language where adaptors have to be built to get the functionality of lisp rather than lisp itself (or something like that.) I see his point but if the effort of getting lisp to work with C/C++ based code is greater than the pain of using an LFM, why not make the best of an LFM? Has anyone had the same experience? Or am I putting the "ass" in masses?