4 ms·
The fact that Functions are Objects that can have properties/methods is supremely undervalued. Are there other languages that do this so nicely? It's t
by CharlieDigital 3y ago
The fact that Functions are Objects that can have properties/methods is supremely undervalued.
Are there other languages that do this so nicely? It's the perfect blend of OO and functional.
Yes. C#. The equivalent are `Func` and `Action` types representing functions with a return and without a return. In fact, the JavaScript lambda expression looks awfully familiar to C#.
One of the snippets below is C# and the other is TypeScript:
var echo = (string message) => Console.Write($"You said: {message}");
var echo = (message: string) => console.log(`You said: ${message}`);
The same signature in C# and TypeScript:
var Apply = (Func<string, string> fn, string input) => fn(input);
var result = Apply(input => ..., "some_string");
var apply = (fn: (input: string) => string, input: string) => fn(input)
var result = apply(input => ..., input);
The C# can version can also be written like:
var Apply = (Func<string, string> fn, string input) => fn(input);
var lowercase = (string input) => input.ToLowerInvariant();
var result = Apply(lowercase, "HELLO, WORLD");
For the curious, I have a small repo that shows just how similar JavaScript, TypeScript, and C# are: https://github.com/CharlieDigital/js-ts-csharp https://github.com/CharlieDigital/js-ts-csharp
Screen grab of the same logic in JS/TS/C# showing the congruency: https://github.com/CharlieDigital/js-ts-csharp/blob/main/js-ts-csharp.png https://github.com/CharlieDigital/js-ts-csharp/blob/main/js-...
- nightpool 3y agothis doesn't really address OP's point, where in JS you can do: const foo = () => doSomething; foo.help = "this is a description of the function"; const commands = [foo]; // print help commands.forEach(c => console.log(c.name, c.help || "No help is available for this function"); Presumably this isn't possible in C# because it's statically typed, so the object returned by "() => doSomething" can't be converted into one that supports adding more properties?
- CharlieDigital 3y agoIt can. .NET/C# has a `dynamic` type (aka `ExpandoObject`). That would be one way to do it (but would require casting to invoke). It's not exactly the same since you'd assign the `Func`/`Action` to a property of the `dynamic`. `dynamic` is generally avoided due to how easy it is to get into a pickle with it and also performance issues. An alternate in this case is probably to return a tuple which I think is just as good/better. Example: var log = (object message) => Console.WriteLine(message); var foo = () => log("Hello, World"); var fn1 = (foo, "This is the help text"); var commands = new[] { fn1 }; commands.ToList().ForEach(c => { var (fn, help) = c; log(fn.Method.Name); log(help ?? "No help is available for this function"); }); https://dotnetfiddle.net/szxb9F https://dotnetfiddle.net/szxb9F The tuple can also take named properties like this: var log = (object message) => Console.WriteLine(message); var foo = () => log("Hello, World"); var commands = new (Action fn, string? help)[] { (foo, "This is the help text"), (foo, null) }; commands.ToList().ForEach(c => { log(c.fn.Method.Name); log(c.help ?? "No help is available for this function"); }); https://dotnetfiddle.net/oPK1d8 https://dotnetfiddle.net/oPK1d8 Alternatively, use anonymous types: var log = (object message) => Console.WriteLine(message); var foo1 = () => log("Hello, World"); var foo2 = () => log("Hello, Neighbor"); var bar = new[] { new { doSomething = foo1, help = "This is foo1's help text" }, new { doSomething = foo2, help = "This is foo2's help text" }, }; bar.ToList().ForEach(b => { var (fn, help) = (b.doSomething, b.help); fn(); log(help); }); https://dotnetfiddle.net/KyBtgZ https://dotnetfiddle.net/KyBtgZ The next release of C# (12) will include named tuple types: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-12.0/using-alias-types#summary https://learn.microsoft.com/en-us/dotnet/csharp/language-ref... Very much looking forward to this since it gives you a lot of the same power of the JavaScript map/TS `Record`. > ...because it's statically typed While this is true, the `dynamic`/`ExpandoObject` is an oddity and lets you do weird things like multiple dispatch on .NET (https://charliedigital.com/2009/05/28/visitor-pattern-in-c-4-0/ https://charliedigital.com/2009/05/28/visitor-pattern-in-c-4...). But C# has a bunch of compiler tricks with regards to anonymous types that can mimic JS objects to some extent. The tuple type is probably a better choice in most cases, however.
- grumblingdev 3y agoGreat repo. I've always wanted to build a transpiler from TS to every other language. We have so many languages but all syntax is so similar in the end. I often wonder how much of the code we write is actually doing something not possible in another language. Like runtime-specific, or low-level stuff. Most of the business logic...loops and if statements are rather similar.