

BODOL – inspired by Haskell, Clojure and Shen - AndreasFrom
https://github.com/bodil/BODOL

======
CoffeeDregs
Wow. I've been searching for my next language and this could be perfect. I
loved Haskell and really miss static typing, type inference, etc, but got
tired of living in mondads. I've been looking at Clojure a lot anyways, but
really dislike dynamic typing. If I could have Clojure with static types, I'd
be done searching.

Though BODOL mentions static typing, I didn't see any examples... What did I
miss?

~~~
runT1ME
>but got tired of living in mondads

Why? Too limiting, syntax too cumbersome, transformers suck?

~~~
CoffeeDregs
Kind of all of the above, but I started to realize that I was writing code in
a very imperative fashion, since, although I do understand monads and how they
keep IO pure, I felt weird writing very imperative feeling code. e.g. pseudo:

    
    
        do
          f <- openFile 'somefile.txt'
          r <- read f
          s <- doSomethingToR r
    

Kinda looked like every other language. Except no one else spoke it and the
libraries (at the time) was of highly varying quality..

Also, while I was comfortable with monads, I never got comfortable with monad
transformers. I had one monad that was a stack of something like 4-5 monad
transformers and I started to feel as though I was losing touch with the
beauty of Haskell.

~~~
dchichkov
How about Python? You can write IO in a relatively functional fashion in
Python:

    
    
      print sum(float(line) for line in open('somefile.txt'))

~~~
swift
Heh, that's actually slightly shorter than this Haskell version:

    
    
      print =<< sum . map read . lines <$> readFile "somefile.txt"
    

Someone can probably golf this shorter, though. =)

~~~
evincarofautumn
This defaults Num, Read, and Show to Integer—I try to avoid defaulting because
it’s kind of a language wart. And speaking of golf: same length but one fewer
import by killing the fmap.

    
    
        print . sum . map read . lines =<< readFile "somefile.txt"

~~~
tome
Much clearer. I slightly prefer the following though:

    
    
        ((print . sum . map read . lines) <=< readFile) "somefile.txt"

~~~
evincarofautumn
Pointfree makes more sense for a definition, I think:

    
    
        sumFileLines = print . sum . map read . lines <=< readFile
    

Less so inline because of the excessive parentheses or ($).

~~~
dchichkov
There should be one-- and preferably only one --obvious way to do it.

------
tzaman
I wish developers had more sense of marketing in general - with all due
respect to it's author(s) but BODOL (the word) sounds,... well strange,
unsexy, uninteresting. It really doesn't do the language itself any justice!

~~~
biot
To me, it sounds like a lisp-variant of COBOL:

    
    
          (IDENTIFICATION DIVISION.
           (PROGRAM-ID. HELLO-WORLD.)
           (PROCEDURE DIVISION.
              ((DISPLAY 'Hello, world'.)
               (STOP RUN.))))

~~~
derleth
COBOL does have one thing worth stealing, though, which is its data definition
language and automatic parser generation facility in the core language.

Essentially, COBOL allows programmers to declare what their input file looks
like and the compiler generates code that does all of the work of parsing the
input and getting the data into the relevant variables.

Because COBOL comes from the (Big) Iron Age, this is all in terms of record-
oriented files with fixed-width fields; a modern re-implementation of the
concept would have to operate in terms of nested data structures (XML, JSON,
sexps, etc.), which a Lisp-like's syntax is well-equipped to describe anyway.

------
codewright
Bodil Stokke is a good person to follow in general (on Github and Twitter) if
you're into Clojure.

The name made me chuckle.

The Hindley-Milner actually makes seeing where the type system comes in a
little difficult with these examples.

Hopefully see more code soon.

~~~
masklinn
The type system's only planned, not implemented for now.

------
tieTYT
This looks really cool and I hope it takes off.

I spent 2-4 weeks really trying hard to learn Haskell and I loved it. But when
I tried to make something practical with it, I got so frustrated with its
dependency manager (cabal) and its lack of support for Windows that I dropped
it for Clojure.

I love Clojure's ecosystem, its ability to use any Java library, and its (lack
of) syntax.

But I really miss the language features of Haskell. I think Clojure lets you
get away with a lot of imperative style programming. You can have a function
deep down in the bowels of your code perform side effects if you want. Haskell
makes you define these in one place and forces you to separate it from the
rest of your code (at least that's what the beginners books led me to
believe).

A language that combines the benefits of both sounds like a dream.

~~~
cantankerous
Haskell user, here. What precisely bugged you so much about Cabal? I can
sympathize with the lack of Windows support. I love Haskell so much I ditched
Windows for it, though.

~~~
tieTYT
First know that my background is Java so I'm used to write once, run anywhere.
Haskell didn't feel this way at all. Also, I shouldn't have specifically named
Cabal. My complaint was about my experience with Haskell's ecosystem more than
just its dependency management app. That said I find leiningen really easy to
use. That may just be because I understand maven though.

My first project attempt was to write a web crawler that processed the data it
downloaded. There seemed to be a library that was PERFECT for that named
shpider: <http://hackage.haskell.org/package/shpider>

But, I couldn't install it because it depends on the curl library and the curl
library depends on linux binaries. I develop on Windows. The people in the IRC
channel kept on telling me the path of least resistance is to switch my OS.
But I'm not willing to do that, especially if it's just for a practice
project.

I was told I should be using http-conduit (or something) instead. But that was
lower level than shpider so not ideal. I tried to install that and I got an
error, too. Apparently the project owner had an incorrect config file and it
was trying to use a version of the fault library that it was incompatible with
(he fixed that the next day which was great. But the only reason I could have
figured out my problem is with a team of people on IRC holding my hand through
it). I can't blame Cabal for that, but for a complete newbie who has no idea
what's going on, it's extremely intimidating.

Long story short, I tried installing ~10 libraries with Cabal and only one
installed smoothly. All the others had me googling for obscure forum posts.
Sometimes I could "trick" cabal into installing the library but when I'd use
it I'd get a runtime error related to a bad install. I've never ever ever had
a problem like this with leiningen. But again, I'm experienced with maven.

On top of that, Cabal seems to install everything in a global namespace which
scares me. If your Project1 needs LibraryX version 1 and Project2 needs
LibraryX version 2 and these versions are incompatible, what do you do? Use
something like cabal-dev I was told. But I have no idea what I'm doing with
Cabal as it is. If something goes wrong with an abstraction on top of it, I'm
totally screwed when it comes to debugging my problem.

I think I get why Haskell did this. Time is precious and if you need something
like Curl, your OS has Curl and you don't want to make it your business to
rewrite Curl in Haskell, you'd just reuse the OS library. But if I use a
different OS, you kind of screwed me.

I love the Haskell language and miss all its lovely features. But if the
language requires me to change my OS to develop anything useful, that's a
nonstarter.

~~~
anonymous
Regarding curl, you can just compile it on windows with msvc. It's not
completely trivial, since you also need to compile openssl with it for ssl
support, but it's perfectly doable.

~~~
Guvante
"Easy to use" is not manually compiling multiple libraries together using a
paid product. :)

------
nnq
She's pretty fast to dismiss Shen:

> Shen is a splendid compromise, but I found myself wishing it came with
> Haskell's uncompromising purity and Standard ML's straightforward type
> system.

I guess Haskell/ML minded people have a reason to think this way, but I'd be
more interested to know whether _someone is doing anything interesting with
Shen. Have you got any "production" code written in it and running to show
off?_

EDIT: sorry! ...fixed the gender bug.

~~~
pi18n
I would dismiss Shen just for the weird license. What if I like it and want to
use it in an embedded product or somewhere? I'd have to make sure any
derivative work adheres to his spec even if it's only intended to run one
library.

~~~
hga
Bingo; I already have, after trying to convince the author to at minimum make
the license short enough to be less ambiguous. He's _absolutely_ sure it's not
a problem no matter how many people tell him it is.

This could also be a factor in the BODOL author's dismissal.

~~~
pi18n
Further down he writes the rationale is to prevent fragmentation of the
community; from what I have seen it prevents developers who otherwise might
from joining the community.

It's not like e.g. Python or Haskell have a fragmentation problem despite
permissible licenses. Scheme has fragmentation problems but that seems to be a
symptom of simple implementation and lack of a common set of libraries.

I think Shen is interesting, but if I used it I'd only be mining it for ideas
to apply in other languages. It would make far more sense to me if he allowed
derivatives iff they did not use the name.

~~~
hga
I don't disagree with the goal of preventing fragmentation, and I'd even be
willing to play the flag game (i.e. have my version focus on SMP functionality
in both senses of the latter, while observing the official spec with a
different flag).

It's the long winded, says the same things at least 5 (!) different times and
ways, and therefore subject to many interpretations license, which is then
subject to whims of the author or an external board (compare to Java, where
_in theory_ passing a suite of tests allows you to offer a version of
Java(TM)).

I'm not going to invest serious effort in something that might get killed
simply for political reasons including different interpretations of the
license; even if I trusted the good will of everyone involved, sooner or later
the players will change.

------
habosa
Looks cool but why the λ and ƒ? That's not practical for anyone. I guess it's
a cool novelty for functional types but it will confuse anyone who sees BODOL
in the wild.

I know it's a nitpick, but it seems strange to include characters that aren't
on the keyboard as part of the default syntax.

~~~
phowat
I thought the same at first. But as I was checking out the language, I simply
created keybindings in my .vimrc to both characters. Now if I press ALT+f, I
get the ƒ character. Less key presses than any other function definition
keyword from any language I ever used. And I know I could have done the same
thing for the other languages, but the fact is that I never did.

------
olegbl
Looks cool, but seems to immediately fall into Lisp's parentheses hell even in
the Hello World apps.

~~~
codygman
(what (do (you (mean ; vim/emacs completes the rest for me

I find the parenthesis make me more aware of scope than other languages.

------
plainOldText
Great, I think it has a very clean, elegant syntax, which is very nice; I
don't write much lisp but it seems that every time I look at a piece of code
in lisp, I tend to appreciate even more how minimalist lisp is.

~~~
codygman
#lang racket

(define (naive-for start end my-body) (let ([operator (if (< start end) + -)])
(my-body) (cond [(not (eq? start end)) (naive-for (operator start 1) end my-
body)])))

(naive-for 1 -2 (lambda () (displayln "For loop? Who needs those!")))

~~~
yoklov
Clearly this calls for a macro

    
    
        (define-syntax naive-for
          (syntax-rules ()
            [(naive-for start end body ...)
             (let ([op (if (< start end) + -)])
               (let loop ([s start] [e end])
                 (begin body ...)
                 (cond [(not (eq? s e))
                        (loop (op s 1) e)])))]))
    
        (naive-for 1  -2
          (displayln "Lambda? What lambda?"))

~~~
codygman
Thank you! I haven't gotten to macros yet, but I can see they are very
straight-forward!

------
pi18n
I don't get why -> syntax is used if part of the goal is homoiconicity.

Nitpicking aside, I fully approve of the goals and look forward to browsing
the source.

~~~
hermanhermitage
Using infix -> doesn't break homoiconicity. The program is still encoded as
sexprs.

~~~
pi18n
It seems like it would mess with macros, because you'd now need to parse the
sexpr to make sure it isn't a ->. And what is the point of homoiconicity if
you cannot easily rewrite any given expression? I dunno, it strikes me as odd,
but there's also a high chance I'm missing something important about ->'s.

------
Tobu
Lisp homoiconicity + strong, expressive static typing seem hard to mix.
Apparently Shen does it? Is the type system similar to ML with
quotations/antiquotations?

------
the1
looks similar to <http://i.webscale.info/lipl/core.html> except that LIPL
doesn't have pattern matching

------
a-nikolaev
This is just a toy language, an excercise, not a real language. And it's easy
to implement a simple purely functional language in another functional
language.

~~~
squidsoup
It's easy to belittle other people's efforts, but that doesn't mean you
should.

~~~
a-nikolaev
I don't belittle. It is a nice work, but it just does not look more than an
excercise in programming languages implementation.

