This question already has answers here:
Are Elixir variables really immutable?
(5 answers)
Closed 4 years ago.
I'm currently studying Elixir and I'm reading "Functional Web Development with Elixir, OTP and Phoenix", which imo is a great book.
Working at the state machine chapter, I came up with the following code:
defmodule IslandsEngine.Rules do
alias __MODULE__
defstruct state: :initialized
def new(), do: %Rules{}
def check(%Rules{state: :initialized} = rules, :add_player), do:
{:ok, %Rules{rules | state: :players_set}}
def check(_state, _action), do: :error
end
The code above should work as a fully functional state machine.
I'll paste above a few of iex commands:
iex(1)> alias IslandsEngine.Rules
IslandsEngine.Rules
iex(2)> rules = Rules.new()
%IslandsEngine.Rules{state: :initialized}
iex(3)> {:ok, rules} = Rules.check(rules, :add_player)
{:ok, %IslandsEngine.Rules{state: :players_set}}
iex(4)> rules.state
:players_set
So as you can see, the state struct has changed from :initialized to :add_player. Great.
My question is: is state: struct really immutable? I mean, the method check/1 returns a copy of the struct with a state: :players_set statement, which follows a correct functional pattern... but how does it "overwrite" the current status without modifying it directly?
Thanks a lot!
Elixir data-structures are indeed immutable. But what happens is that function calls return a completely new value (that is different from the original depending on the function you called).
As for the "changing the variable's value", that's an added feature in Elixir (over the original Erlang language). The variable's value doesn't actually change, it's just rebinded to the new one. The old ones are automatically garbage collected by the Erlang VM.
So in your example:
# This returns a completely new `%Rules{}` struct and rebinds
# the `rules` variable to the new term
{:ok, rules} = Rules.check(rules, :add_player)
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
Rust's .expect() is one of the most surprising names in the Result/Option space. While unwrap makes sense -- get a value from a Result by "unwrapping" it -- expect is surprisingly counterintuitive (to me).
Since so much of Rust is inspired by conventions from functional programming languages, I have been assuming that this is another example of "strange homage to obscurity," but when I asked the Duck it couldn't find an answer for me.
So, I give up. Why is .expect() the name for Rust's .unwrap_or_panic_with_this_message() function? Is this a reference to a feature in yet another functional language? Is it back-handed shade (or a complement) to Tcl? The result of too many late nights and too much Espresso at Mozilla?
What is the etymology of this plucky (but fierce!) little member of the standard library?
Edit:
Great news, everyone! After more than a year, we now have both an "explanation" in #GManNickG's tremendously well-researched and documented answer, below, and a "mental model" provided by #Peng's comment and link:
https://doc.rust-lang.org/std/error/index.html#common-message-styles
In short, it is now recommended that diagnostics for expect() should be written as "expect...should" or maybe "expect...should have". This makes more sense in the diagnostic output (see the link for examples) but also makes the source code scan better:
foo.expect("something bad happened") // NO!
foo.expect("gollywumpus should be current") // YES!
Summary:
No explicit reason for the name is given. However, it is incredibly likely the name comes from the world of parsers, where one "expects" to see a particular token (else the compilation fails).
Within rustc, the use of expect-like functions long predate use within Option. These are functions like expect(p, token::SEMI) to expect to parse a semicolon and expect_word(p, "let") to expect to parse the let keyword. If the expectation isn't met, compilation fails with an error message.
Eventually a utility function was added within the compiler that would expect not a specific token or string, but that a given Option contained a value (else, fail compilation with the given error message). Over time this was moved to the Option struct itself, where it remains today.
Personally, I don't find it unusual at all. It's just another verb you can do to the object, like unwrapping or taking or mapping its value. Expecting a value (else, fail) from your Option seems quite natural.
History:
The oldest commit of note is the following:
https://github.com/rust-lang/rust/commit/b06dc884e57644a0c7e9c5391af9e0392e5f49ac
Which adds this function within the compiler:
fn expect<T: copy>(sess: session, opt: option<T>, msg: fn() -> str) -> T {
alt opt {
some(t) { t }
none { sess.bug(msg()); }
}
}
As far as I can tell, this is the first function named "expect" that deals with inspecting an Option. Observe in particular this example use-case within the commit (which was implementing support for class methods!):
#debug("looking up %? : %?", def, class_doc);
let the_field = expect(tcx.sess,
decoder::maybe_find_item(def.node, class_doc),
{|| #fmt("get_field_type: in class %?, field ID %? not found",
class_id, def)});
If the result of decoder::maybe_find_item is None, compilation will fail with the given error.
I encourage you to look at the parser code in this commit - there is extensive use of other expect-esque functions: e.g., expect(p, token::RPAREN) and expect_word(p, "let"). The name of this new function is almost obvious in this environment.
Eventually, the utility of this function was extracted and placed within Option itself:
https://github.com/rust-lang/rust/commit/e000d1db0ab047b8d2949de4ab221718905ce3b1
Which looked like:
pure fn expect<T: copy>(opt: option<T>, reason: str) -> T {
#[doc = "
Gets the value out of an option, printing a specified message on failure
# Failure
Fails if the value equals `none`
"];
alt opt { some(x) { x } none { fail reason; } }
}
It's worth noting that sometime later, there was eventually an (additional) function named unwrap_expect added in:
https://github.com/rust-lang/rust/commit/be3a71a1aa36173ce2cd521f811d8010029aa46f
pure fn unwrap_expect<T>(-opt: option<T>, reason: ~str) -> T {
//! As unwrap, but with a specified failure message.
if opt.is_none() { fail reason; }
unwrap(opt)
}
Over time these were both subsumed by an Expect trait, which Option implemented:
https://github.com/rust-lang/rust/commit/0d8f5fa618da00653897be2050980c800389be82
/// Extension trait for the `Option` type to add an `expect` method
// FIXME(#14008) should this trait even exist?
pub trait Expect<T> {
/// Unwraps an option, yielding the content of a `Some`
///
/// # Failure
///
/// Fails if the value is a `None` with a custom failure message provided by
/// `msg`.
fn expect<M: Any + Send>(self, m: M) -> T;
}
Spoiler for that TODO: that trait no longer exists. It was removed shortly after per:
https://github.com/rust-lang/rust/issues/14008.
More or less this is where we are at today.
I think the most likely conclusion is that the use of expect as a meaningful function name long predates its use in Option. Given it says what it does (expect a value or fail) there is little reason to break the pattern.
I am aware that a variable can be dynamically typed with the def keyword in Groovy. But I have also noticed that in some circumstances it can be left out, such as when defining method parameters, eg func(p1, p2) instead of func(def p1, def p2). The latter form is discouraged.
I have noticed that this is extendable to all code - anytime you want to define a variable and set its value, eg var = 2 the def keyword can be safely left out. It only appears to be required if not instantiating the variable on creation, ie. def var1 so that it can be instantiated as a NullObject.
Is this the only time def is useful? Can it be safely left out in all other declarations, for example, of classes and methods?
Short answer: you can't. There are some use cases where skipping the type declaration (or def keyword) works, but it is not a general rule. For instance, Groovy scripts allow you to use variables without specific type declaration, e.g.
x = 10
However, it works because groovy.lang.Script class implements getProperty and setProperty methods that get triggered when you access a missing property. In this case, such a variable is promoted to be a global binding, not a local variable. If you try to do the same on any other class that does not implement those methods, you will end up getting groovy.lang.MissingPropertyException.
Skipping types in a method declaration is supported, both in dynamically compiled and statically compiled Groovy. But is it useful? It depends. In most cases, it's much better to declare the type for a better readability and documentation purpose. I would not recommend doing it in the public API - the user of your API will see Object type, while you may expect some specific type. It shows that this may work if your intention is to receive any object, no matter what is its specific type. (E.g. a method like dump(obj) could work like that.)
And last but not least, there is a way to skip type declaration in any context. You can use a final keyword for that.
class Foo {
final id = 1
void bar(final name) {
final greet = "Hello, "
println greet + name + "!"
}
}
This way you can get a code that compiles with dynamic compilation, as well as with static compilation enabled. Of course, using final keyword prevents you from re-assigning the variable, but for the compiler, this is enough information to infer the proper type.
For more information, you can check a similar question that was asked on SO some time ago: Groovy: "def" keyword vs concrete type
in Groovy it plays an important role in Global and Local variable
if the variable name is same with and without def
def is considered local and without def its global
I have explained here in detail https://stackoverflow.com/a/45994227/2986279
So if someone use with and without it will make a difference and can change things.
So in order to learn OOP-programming, we are tasked du build classes. These classes should us allow getting input() via the terminal. Like "enter 'a''' for a list of all books.
This is my first method and it does not want to work. It SHOULD not take any parameters, it doesn't need any since there is one list it is tasked to read out.
So my code looks like this:
from Library import *
while(True):
print("blabla explaining how to use the program, do you want to 'a', print a list of all books, 'b'.....")
user_choice = input
if(user_choice == 'a'):
Library.list_books()
if(user_choice == 'b'):
#etc.
And the library method looks as follows:
from Book import *
def list_books(self):
for Book.Book in Book.book_list:
print(Book.Book.name)
As you see, it doesn't really need anything in order to function. Why is it then, that it wants a parameter. Obviously, if I remove the 'self' it would work, but that is, as far as I know, not conventional. The only fix I found was adding #classmethod. My boss did not approve of that though and called it cheating.
It may be, that I haven't fully understood what the 'self' does/is, but for now, all I know is, that it doesn't work and I am out of ideas. I am still researching it but either I am too stupid or the sources don't do a good job explaining it to me. I've just been programming python for, like, 2 weeks now and have VERY mild Java skills, so my general programming knowledge is still limited. If you have any sources that explain it well or which help you I'd be very glad to read them.
Thanks in advance!
The self parameter is often added to methods automatically by IDEs. It is primarily used when the method is contained inside of a class.
Take for example the Book class below.
class Book:
author = ""
title = ""
def __init__(self, author, title):
self.author = author
self.title = title
def print_book_information(self):
print("'%s' by %s" % (self.title, self.author))
Since you're just starting with OOP, a lot of this is going to be a bit confusing. First, we declare the class type Book.
class Book:
The next two lines declare variables associated with the Book class. In this case, we want to store the author of the book, as well as the title of the book.
author = ""
title = ""
The next two functions, if you noticed, both have a self parameter. The parameter self references back to the book that you've created. so if I create a book like so:
my_book = Book('Ayn Rand', 'Atlas Shrugged')
It will execute the __init__ method, which sets the value of author and title for our specific book.
self.author = author # Sets our author to be 'Ayn Rand'
self.title = title # Sets our title to be 'Atlas Shrugged'
Now that our class is made, we can do something like
>>> my_book.print_book_information()
'Atlas Shrugged' by Ayn Rand
Notice in the method print_book_information how we use the word self to reference our author and title? The self essentially allows the method to know which specific book you are looking at. Otherwise, the method wouldn't know which book you wanted the title or author for.
Also, in the question you noted that you have a very mild Java background. self performs a similar function to the this keyword from Java, except that you have to include it as a parameter in Python, whereas you don't reference it in the parameters in Java. The following two methods are essentially the same:
# Python
class Hello:
def say_hello(self):
print("Hello!")
// Java
public class Hello
{
public void say_hello()
{
System.out.println("Hello!");
}
}
Might be a typo or two in the java, haven't used it in the past 5 years or so.
I'm having a look at the code at this page:
http://golang.org/pkg/net/http/
And there's one thing I don't understand - at some point, a new structure is created and initialized like this:
client := &http.Client{
CheckRedirect: redirectPolicyFunc,
}
Why use & when creating this structure?
I've also read this blog post and structs are initialized like this:
r := Rectangle{}
What is the difference between both and how should I know which one to use?
The difference is in the type of your variable.
client := &http.Client{
makes client of type *http.Client
while
client := http.Client{
builds a http.Client.
The top one is returning a pointer. It is a Go idiom instead of using new. The second one is just a value object. If you need a pointer use the top.
Check the effective go doc for more about this
http://golang.org/doc/effective_go.html#allocation_new
In object-oriented programming, in order for an object to have dynamic lifetime (i.e. not tied to the current function call), it needs to be dynamically allocated in a place other than the current stack frame, thus you manipulate the object through a pointer. This is such a common pattern that in many object-oriented languages, including Java, Python, Ruby, Objective-C, Smalltalk, JavaScript, and others, you can only deal with pointers to objects, never with an "object as a value" itself. (Some languages though, like C++, do allow you to have "objects as values"; it comes with the RAII idiom which adds some complexity.)
Go is not an object-oriented language, but its ability to define custom types and define methods that operates on that custom type, can be made to work very much like classes and methods. Returning a pointer to the type from the "constructor" function allows the "object" to have a dynamic lifetime.
When we use reference, we use a single item throughout the program runtime. Even if we assign that to a new variable or pass through a function. But when we use value, we make new copies of individual items.
( Reference is not right word according to golang convention. "Address of value" would be more appropriate here https://golang.org/ref/spec#Package_initialization )
An example will make it much clear I hope.
type Employee struct {
ID int
Name string
Address string
}
func main() {
andy := &Employee{}
andy.Name = "Andy"
brad := andy
brad.Name = "Brad"
fmt.Println(andy.Name)
}
The result of this code block would be:
Brad
As we made new variable from it but still referring to same data. But if we use value instead of reference and keep the rest of the code same.
// from
andy := &Employee{}
// to
andy := Employee{}
This time the result would be:
Andy
As this time they both are individual items and not referring to same data anymore.
Hypothetic and academic question.
pseudo-code:
<pre><code>
class Book{
read(theReader)
}
class BookWithMemory extends Book {
read(theReader, aTimestamp = null)
}
</pre></code>
Assuming:
an interface (if supported) would prohibit it
default value for parameters are supported
Notes:
PHP triggers an strict standards error for this.
I'm not surprised that PHP strict mode complains about such an override. It's very easy for a similar situation to arise unintentionally in which part of a class hierarchy was edited to use a new signature and a one or a few classes have fallen out of sync.
To avoid the ambiguity, name the new method something different (for this example, maybe readAt?), and override read to call readAt in the new class. This makes the intent plain to the interpreter as well as anyone reading the code.
The actual behavior in such a case is language-dependent -- more specifically, it depends on how much of the signature makes up the method selector, and how parameters are passed.
If the name alone is the selector (as in PHP or Perl), then it's down to how the language handles mismatched method parameter lists. If default arguments are processed at the call site based on the static type of the receiver instead of at the callee's entry point, when called through a base class reference you'd end up with an undefined argument value instead of your specified default, similarly to what would happen if there was no default specified.
If the number of parameters (with or without their types) are part of the method selector (as in Erlang or E), as is common in dynamic languages that run on JVM or CLR, you have two different methods. Create a new overload taking additional arguments, and override the base method with one that calls the new overload with default argument values.
If I am reading the question correctly, this question seems very language specific (as in it is not applicable to all dynamic languages), as I know you can do this in ruby.
class Book
def read(book)
puts book
end
end
class BookWithMemory < Book
def read(book,aTimeStamp = nil)
super book
puts aTimeStamp
end
end
I am not sure about dynamic languages besides ruby. This seems like a pretty subjective question as well, as at least two languages were designed on either side of the issue (method overloading vs not: ruby vs php).