Can the spread operator be used to supply function arguments? - dart

I'm writing class that extends statelessWidget, its build method returns Text() widget. and I need to pass to it text options (alignment, stile etc.) that came from constructor in Map<dynamic, dynamic>. Why I can't use spread operator like this
final Map textOptions;
final String text;
build(BuildContext context) {
return Text(text, ...textOptions)
}

You currently can use the spread operator only for collection literals ([] for List, {} for Map or Set).
From Bob Nystrom's article introducing Dart 2.3's new features:
A spread can only appear in a place that can gracefully handle
receiving zero or more values. Without completely overhauling the
language’s execution model and turning it into Icon (which I find
strangely appealing, but probably not practical…), there aren’t too
many places that fit that constraint. Basically collection literals
and maybe positional argument lists. (I wrote a proposal for the
latter, but it’s quite complex so we aren’t doing it, at least not
right now.)
That proposal doesn't quite cover what you want, which is to spread a Map into optional named arguments, however.

I don't think that the spread operator can be used with something else than List and arrays [1, 2, 3].
Maybe you could first convert your Map to a List and then use the spread operator.

Related

Lua Terminology related to OOP

To be to the point; I've done Lua for awhile, but never quite got the terminology down to specifics, so I've been Googling for hours and haven't come up with a definitive answer.
Related to OOP in Lua, the terminology used include:
Object
Class
Function
Method
Table
The question is, when are these properly used? Such as in the example below:
addon = { }
function addon:test_func( )
return 'hi'
end
Q: From my understanding with Lua and OOP, addon is a table, however, I've read that it can be an object as well -- but when it is technically an object? After a function is created within that table?
Q: test_func is a function, however, I've read that it becomes a "Method" when it's placed within a table (class).
Q: The entire line addon:test_func( ), I know the colon is an operator, but what is the term for the entire line set of text? A class itself?
Finally, for this example code:
function addon:test_func( id, name )
end
Q: What is id and name, because I've seen some people identify them as arguments, but then other areas classify them as parameters, so I've stuck with parameters.
So in short, what is the proper terminology for each of these, and when do they become what they are?
Thanks
From my understanding with Lua and OOP, addon is a table, however, I've read that it can be an object as well -- but when it is technically an object? After a function is created within that table?
Object is not a well-defined term. I've seen it defined (in C) as any value whatsoever. In Lua, I would consider it synonymous with a table. You could also define it as an instance of a class.
test_func is a function, however, I've read that it becomes a "Method" when it's placed within a table (class).
You're basically right. A method is any function that is intended to be called with the colon notation. Metamethods are also methods, because, like regular methods, they define the behavior of tables.
The entire line addon:test_func( ), I know the colon is an operator, but what is the term for the entire line set of text? A class itself?
There's no name for that particular piece of code. It's just part of a method definition.
Also, I wouldn't call the colon an operator. An operator would be the plus in x + y where x and y both mean something by themselves. In addon:test_func(), test_func only has meaning inside the table addon, and it's only valid to use the colon when calling or defining methods. The colon is actually a form of syntactic sugar where the real operator is the indexing operator: []. Assuming that you're calling the method, the expansion would be: addon['test_func'](addon).
What is id and name, because I've seen some people identify them as arguments, but then other areas classify them as parameters, so I've stuck with parameters.
They're parameters. Parameters are the names that you declare in the function signature. Arguments are the values that you pass to a function.

What are the steps in doing incrementation in erlang?

increment([]) -> [];
increment([H|T]) -> [H+1|increment(T)].
decrement([]) -> [];
decrement([H|T]) -> [H-1|decrement(T)].
So I have this code but I don't know how they properly work like in java.
Java and Erlang are different beasts. I don't recommend trying to make comparisons to Java when learning Erlang, especially if Java is the only language you know so far. The code you've posted is a good example of the paradigm known as "functional programming". I'd suggest doing some reading on that subject to help you understand what's going on. To try to break this down as far as Erlang goes, you need to understand that an Erlang function is completely different from a Java method.
In Java, your method signature is composed of the method name and the types of its arguments. The return type can also be significant. A Java increment method like the function you wrote might be written like List<Integer> increment(List<Integer> input). The body of the Java method would probably iterate through the list an element at a time and set each element to itself plus one:
List<Integer> increment(List<Integer> input) {
for (int i = 0; i < input.size; i++) {
input.set(i, input.get(i) + 1);
}
}
Erlang has almost nothing in common with this. To begin with, an erlang function's "signature" is the name and arity of the function. Arity means how many arguments the function accepts. So your increment function is known as increment/1, and that's its unique signature. The way you write the argument list inside the parentheses after the function name has less to do with argument types than with the pattern of the data passed to it. A function like increment([]) -> ... can only successfully be called by passing it [], the empty list. Likewise, the function increment([Item]) -> ... can only be successfully called by passing it a list with one item in it, and increment([Item1, Item2]) -> ... must be passed a list with two items in it. This concept of matching data to patterns is quite aptly known as "pattern matching", and you'll find it in many functional languages. In Erlang functions, it's used to select which head of the function to execute. This bears a rough similarity to Java's method overloading, where you can have many methods with the same name but different argument types; however a pattern in an Erlang function head can bind variables to different pieces of the arguments that match the pattern.
In your code example, the function increment/1 has two heads. The first head is executed only if you pass an empty list to the function. The second head is executed only if you pass a non-empty list to the function. When that happens, two variables, H and T, are bound. H is bound to the first item of the list, and T is bound to the rest of the list, meaning all but the first item. That's because the pattern [H|T] matches a non-empty list, including a list with one element, in which case T would be bound to the empty list. The variables thus bound can be used in the body of the function.
The bodies of your functions are a very typical form of iterating a list in Erlang to produce a new list. It's typical because of another important difference from Java, which is that Erlang data is immutable. That means there's no such concept as "setting an element of a list" like I did in the Java code above. If you want to change a list, you have to build a new one, which is what your code does. It effectively says:
The result of incrementing the empty list is the empty list.
The result of incrementing a non-empty list is:
Take the first element of the list: H.
Increment the rest of the list: increment(T).
Prepend H+1 to the result of incrementing the rest of the list.
Note that you want to be careful about how you build lists in Erlang, or you can end up wasting a lot of resources. The List Handling User's Guide is a good place to learn about that. Also note that this code uses a concept known as "recursion", meaning that the function calls itself. In many popular languages, including Java, recursion is of limited usefulness because each new function call adds a stack frame, and your available memory space for stack frames is relatively limited. Erlang and many functional languages support a thing known as "tail call elimination", which is a feature that allows properly written code to recurse indefinitely without exhausting any resources.
Hopefully this helps explain things. If you can ask a more specific question, you might get a better answer.

In Dart can hashCode() method calls return different values on equal (==) Objects?

My immediate project is to develop a system of CheckSums for proving that two somewhat complex objects are (functionally)EQUAL - in the sense that they have the same values for the critical properties. (Have discovered that dates/times cannot be included, so can't use JSON on the bigger object - duh :) (For my purposes) ).
To do this calling the hashCode() method on selected strings seemed to be the way to go.
Upon implementing this, I note that in practice I am getting very different values on multiple runs of highest level objects that are functionally 'identical'.
There are a number of "nums" that I have not rounded, there are integers, bools, Strings and not much more.
I have 'always' thought that a hashCode on the same set of values would return the same number, am I missing something?
BTW the only context that I have found material on hashCode() has been with WebSockets.
Of course I can write my own String to a unique value but I want to understand if this is a problem with Dart or something else.
I can attempt to answer the question posed in the title: "Can hashCode() method calls return different values on equal (==) Objects?"
Short answer: hash codes for two objects must be the same if those two objects are equals (==).
If you override hashCode you must also override equals. Two objects that are equal, as defined by ==, must also have the same hash code.
However, hash codes do not have to be unique. That is, a perfectly valid hash code is the value 1. A good hash code, however, should be uniformly distributed.
From the docs from Object:
Hash codes are guaranteed to be the same for objects that are equal
when compared using the equality operator ==. Other than that there
are no guarantees about the hash codes. They will not be consistent
between runs and there are no distribution guarantees.
If a subclass overrides hashCode it should override the equality
operator as well to maintain consistency.
I found the immediate problem. The object stringify() method, at one level, was not getting called, but rather some stringify property that must exist in all objects (?).
With this fixed everything is working as exactly as I would expect, and multiple runs of our Statistical Studies are returning exactly the same CheckSum at the highest levels (based on some 5 levels of hierarchy).
Meanwhile the JSON.stringify has continued to fail. Even in the most basic object. I have not been able to determine what is causing to fail. Of course, the question is not how "stringify" is accomplished.
So, empirically at least, I believe it is true that "objects with equal properties" will return equal checkSums in Dart. It was decided to round nums, I don't know if this was causing a problem - perhaps good to be aware of? And, of course, remember to be beware of things like dates, times, or anything that could legitimately vary.
_swarmii
The doc linked by Seth Ladd now include info:
They need not be consistent between executions of the same program and there are no distribution guarantees.`
so technically hashCode value can be change with same object in different executions for your question:
I have 'always' thought that a hashCode on the same set of values would return the same number, am I missing something?

Why don't F# lists have a tail pointer

Or phrased another way, what kind of benefits do you get from having a basic, singly linked list with only a head pointer? The benefits of a tail pointer that I can see are:
O(1) list concatenation
O(1) Appending stuff to the right side of the list
Both of which are rather convenient things to have, as opposed to O(n) list concatenation (where n is the length of the left-side list?). What advantages does dropping the tail pointer have?
F#, like many other functional[-ish] languages, has a cons-list (the terminology originally comes from LISP, but the concept is the same). In F# the :: operator (or List.Cons) is used for cons'ing: note the signature is ‘a –> ‘a list –> ‘a list (see Mastering F# Lists).
Do not confuse a cons-list with an opaque Linked List implementation which contains a discrete first[/last] node - every cell in a cons-list is the start of a [different] list! That is, a "list" is simply the chain of cells that starts at a given cons-cell.
This offers some advantages when used in a functional-like manner: one is that all the "tail" cells are shared and since each cons-cell is immutable (the "data" might be mutable, but that's a different issue) there is no way to make a change to a "tail" cell and flub up all the other lists which contain said cell.
Because of this property, [new] lists can be efficiently built - that is, they do not require a copy - simply by cons'ing to the front. In addition, it is also very efficient to deconstruct a list to head :: tail - once again, no copy - which is often very useful in recursive functions.
This immutable property generally does not exist in a [standard mutable] Double Linked List implementation in that appending would add side-effects: the internal 'last' node (the type is now opaque) and one of the "tail" cells are changed. (There are immutable sequence types that allow an "effectively constant time" append/update such as immutable.Vector in Scala -- however, these are heavy-weight objects compared to a cons-list that is nothing more than a series of cells cons'ed together.)
As mentioned, there are also disadvantages a cons-list is not appropriate for all tasks - in particular, creating a new list except by cons'ing to the head is an O(n) operation, fsvo n, and for better (or worse) the list is immutable.
I would recommend creating your own version of concat to see how this operation is really done. (The article Why I love F#: Lists - The Basics covers this.)
Happy coding.
Also see related post: Why can you only prepend to lists in functional languages?
F# lists are immutable, there's no such thing as "append/concat", rather there's just creating new lists (that may reuse some suffixes of old lists). Immutability has many advantages, outside the scope of this question. (All pure languages, and most functional languages have this data structure, it is not an F#-ism.)
See also
http://diditwith.net/2008/03/03/WhyILoveFListsTheBasics.aspx
which has good picture diagrams to explain things (e.g. why consing on the front is cheaper than at the end for an immutable list).
In addition to what the others said: if you need efficient, but yet immutable data structures (which should be an idiomatic F# way), you have to consider reading Chris Okasaki, Purely Functional Data Structures. There is also a thesis available (on which the book is based).
In addition to what has been already said, the Introducing Functional Programming section on MSDN has an article about Working with Functional Lists that explains how lists work and also implements them in C#, so it may be a good way to understand how they work (and why adding reference to the last element would not allow efficient implementation of append).
If you need to append things to the end of the list, as well as to the front, then you need a different data structure. For example, Norman Ramsey posted source code for DList which has these properties here (The implementation is not idiomatic F#, but it should be easy to fix).
If you find you want a list with better performance for append operations, have a look at the QueueList in the F# PowerPack and the JoinList in the FSharpx extension libraries.
QueueList encapsulates two lists. When you prepend using the cons, it prepends an element to the first list, just as a cons-list. However, if you want to append a single element, it can be pushed to the top of the second list. When the first list runs out of elements, List.rev is run on the second list, and the two are swapped putting your list back in order and freeing the second list to append new elements.
JoinList uses a discriminated union to more efficiently append whole lists and is a bit more involved.
Both are obviously less performant for standard cons-list operations but offer better performance for other scenarios.
You can read more about these structures in the article Refactoring Pattern Matching.
As others have pointed out, an F# list could be represented by a data structure:
List<T> { T Value; List<T> Tail; }
From here, the convention is that a list goes from the List you have a reference to until Tail is null. Based on that definition, the benefits/features/limitations in the other answers come naturally.
However, your original question seems to be why the list is not defined more like:
List<T> { Node<T> Head; Node<T> Tail; }
Node<T> { T Value; Node<T> Next; }
Such a structure would allow both appending and prepending to the list without any visible effects to the a reference to the original list, since it still only sees a "window" of the now expanded list. Although this would (sometimes) allow O(1) concatenation, there are several issues such a feature would face:
The concatenation only works once. This can lead to unexpected performance behavior where one concatenation is O(1), but the next is O(n). Say for example:
listA = makeList1 ()
listB = makeList2 ()
listC = makeList3 ()
listD = listA + listB //modified Node at tail of A for O(1)
listE = listA + listC //must now make copy of A to concat with C
You could argue that the time savings for the cases where possible are worth it, but the surprise of not knowing when it will be O(1) and when O(n) are strong arguments against the feature.
All lists now take up twice as much space, even if you never plan to concatenate them.
You now have a separate List and Node type. In the current implementation, I believe F# only uses a single type like the beginning of my answer. There may be a way to do what you are suggesting with only one type, but it is not obvious to me.
The concatenation requires mutating the original "tail" node instance. While this shouldn't affect programs, it is a point of mutation, which most functional languages tend to avoid.
Or phrased another way, what kind of benefits do you get from having a basic, singly linked list with only a head pointer? The benefits of a tail pointer that I can see are:
O(1) list concatenation
O(1) Appending stuff to the right side of the list
Both of which are rather convenient things to have, as opposed to O(n) list concatenation (where n is the length of the left-side list?).
If by "tail pointer" you mean a pointer from every list to the last element in the list, that alone cannot be used to provide either of the benefits you cite. Although you could then get at the last element in the list quickly, you cannot do anything with it because it is immutable.
You could write a mutable doubly-linked list as you say but the mutability would make programs using it significantly harder to reason about because every function you call with one might change it.
As Brian said, there are purely functional catenable lists. However, they are many times slower at common operations than the simple singly-linked list that F# uses.
What advantages does dropping the tail pointer have?
30% less space usage and better performance on virtually all list operations.

Void in constrast with Unit

I would like to understand which is the difference between these two programming concepts. The first represents the absence of data type and at the latter the type exists but there is no information. Additionally, I recognize that Unit comes from functional programming theoretical foundation but I still cannot understand what is the usability of the unit primitive (e.g., in an F# program).
In functional programming, we usually speak of mapping inputs to outputs. This literally means mapping an argument to its return value(s). But if something is going to be a function in the mathematical/category-theory sense, it has to return something. A void value represents that a function returns nothing, which is nonsensical in these terms.
unit is the functional answer to void. It's essentially a type with only one value, (). It has a number of uses, but here's a simple one. Let's say you had something like this in a more traditional imperative language:
public static <T, U> List<U> map(List<T> in, Function<T, U> func) {
List<U> out = new ArrayList<U>(in.size());
for (T t : in) {
out.add(func.apply(t));
}
return out;
}
This applies a particular function func to every element on the list, producing a new list of func's output type. But what happens if you pass in a Function that just prints its arguments? It won't have an output type, so what can you put for U?
In some languages, passing in such a function would break this code (like in C#, where you can't assign void to a generic type). You'd have to resort to workarounds like having an Action<T>, which can get clunky.
This is where the concept of unit is useful: it is a type, but one that may only take on a single value. That greatly simplifies things like chaining and composition, and vastly reduces the number of special cases you have to worry about.
The unit type just makes everything more regular. To an extent you can think of every function in F# as taking a single parameter and returning a single result. Functions that don't need any parameters actually take "unit" as a parameter, and functions that don't return any results return "unit" as a result. This has a variety of advantages; for one, consider how in C# you need both a slew of "Func" delegates to represent functions of various arities that return values, as well as a slew of "Action" delegates that do not return values (because e.g. Func<int,void> is not legal - void cannot be used that way, since it's not quite a 'real' type).
See also F# function types: fun with tuples and currying

Resources