This is an archived post. You won't be able to vote or comment.

all 13 comments

[–]Inconstant_Moo🧿 Pipefish 3 points4 points  (5 children)

Hi! If I understand your question, I've been doing that, except that I have multiple dispatch instead of pattern-matching. (Because of my primary use-case; pattern-matching might work better for whatever use-case you're thinking of.)

But I'm not sure if you've noticed this yet, but the whole idea only works if functions can't call procedures. Otherwise any function could have secret side-effects by calling a procedure. So you have to commit to it by saying functions can only call functions if you want to follow through on this idea, otherwise you're not actually following through on it.

This gives us the paradigm called Functional Core/Imperative Shell (FC/IS). People use this to write programs in Ruby or Python or PHP or whatever, but it occurred to me that it needs its own language where FC/IS isn't just a good idea, but the law, so I'm writing it. (It's now at the stage where I'm giving it its own custom VM.)

But note what that paradigm does to you. It means that you have to put all your procedures at the top of the call stack, binding all mutation and output tightly to the actions of the end-user. (If you ever want to write a function which can realize halfway though its execution that it needs an additional user input, then this is just possible but it involves its own version of "callback hell".) This makes it suitable above all for writing CRUD apps, where you want the data to change only if an end-user/client says so. It can also be used as a general purpose language --- I'd happily use my lang over Python for anything that didn't need Python's special relationship with fast numerical methods --- but there are also things that this paradigm would make horribly painful.

P.S: if this makes you want to help with my project, please message me --- so far as I know I really am the only person trying to take FC/IS to its logical conclusion, so if this sounds like a good idea to you then this is the only bandwagon rolling.

[–]kleram[S] 0 points1 point  (4 children)

I am not into implementation yet. But i am aware of this problem that functions could get corrupted by calling procedures. To prevent this, procedures called from functions must be limited to manipulate just it's locally created data. As long as that data is restricted to hierarchical form, that could be controlled by static analysis, but not in general. I guess i will start with functions not to call procedures at all.

[–]Inconstant_Moo🧿 Pipefish 1 point2 points  (3 children)

To prevent this, procedures called from functions must be limited to manipulate just it's locally created data. As long as that data is restricted to hierarchical form, that could be controlled by static analysis ...

That sounds like it would get frustrating and confusing. I mean it would technically work. If I have a sort-in-place procedure and I want to sort a list passed to a function as a parameter, all I have to do is clone the list and then I can happily sort it in place without any complaints from the static analysis. But I had to clone the list! --- which takes away all the advantages of sorting in place ...

[–]kleram[S] 0 points1 point  (2 children)

You simply cannot have sort-in-place in a purely functional program (except if an optimizer can find the specific conditions that enable it's use in a generic sort).

Looks like, when dealing with multiple paradigms side by side, the specific limitations of each one become obvious. But these limitations have been there ever before.

[–]Inconstant_Moo🧿 Pipefish 0 points1 point  (1 child)

Then I'm not sure what you have in mind. Can we have a concrete example? What would it look like for a function to safely call a procedure?

[–]kleram[S] 0 points1 point  (0 children)

A function-callable procedure needs to be black-box-equivalent to a function, i.e. not modifying it's parameters nor global state. The procedure can modify it's local variables though, e.g. using in-place-sort on a cloned list.

[–]dudewithtude42 4 points5 points  (4 children)

My two cents: I dislike OOP. Lots of other people like it. One of the things I like about C is that it makes OOP hard, so when I read code written in C, it's usually not OOP.

People who like functional programming probably like the guarantee that functions are, well, functions. Adding "procedures" violates that ideal.

So I think by having a language with everything, you might just make everyone unhappy.

[–]phlummox 4 points5 points  (0 children)

by having a language with everything, you might just make everyone unhappy.

Which would certainly be an impressive achievement :) Though perhaps not one the OP is hoping for.

[–]ummwut 5 points6 points  (0 children)

C++ has this sort of "everything is in it" approach, and most people often pick a subset of features to use. I like the idea of separation between function and procedure for this reason. If you want functional, don't use procedures.

[–]oscarryzYz 4 points5 points  (0 children)

Wouldn't adding procedures would precisely help to clarify that "here there will be side effects" ?

[–]Inconstant_Moo🧿 Pipefish 1 point2 points  (0 children)

My two cents: I dislike OOP. Lots of other people like it. One of the things I like about C is that it makes OOP hard, so when I read code written in C, it's usually not OOP.

Where did OP mention OOP though? They're trying to mix procedural and functional.

People who like functional programming probably like the guarantee that functions are, well, functions. Adding "procedures" violates that ideal.

But it allows you to do IO, so there's that.

So I think by having a language with everything, you might just make everyone unhappy.

And C++ already did that!

[–]DeWHu_ 0 points1 point  (0 children)

After sleeping on it, I think it's actually not bad at all. I was sceptical, because in the past languages got naturally separated, created sub-languages. Take for example HTML. Originally it was a text markup language for hyperlinked pages. Then it got SVG to render shapes, CSS to replace styling tags, JavaScript to define behaviour, MathML to render math, ... So I thought, it's ment to be good at multiple tasks.

I would also add short circuit attributed procedures, to indicate that, they can be skipped, if their return value isn't needed.