Creating a Maybe type in Perl 6 Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!How to create a new object instance from a TypeWhat are POD types in C++?What's the canonical way to check for type in Python?How to determine a Python variable's type?What are the differences between type() and isinstance()?How to check if type of a variable is string?Change data type of columns in PandasMaybe types in DWhy does constraining a Perl 6 named parameter to a definite value make it a required value?Are typed signatures for stubbed methods not enforced in roles for Perl6?
Why complex landing gears are used instead of simple,reliability and light weight muscle wire or shape memory alloys?
RSA find public exponent
Central Vacuuming: Is it worth it, and how does it compare to normal vacuuming?
Tannaka duality for semisimple groups
Would color changing eyes affect vision?
Moving a wrapfig vertically to encroach partially on a subsection title
What does it mean that physics no longer uses mechanical models to describe phenomena?
The Nth Gryphon Number
Is CEO the "profession" with the most psychopaths?
I can't produce songs
How to force a browser when connecting to a specific domain to be https only using only the client machine?
Tips to organize LaTeX presentations for a semester
Is there public access to the Meteor Crater in Arizona?
After Sam didn't return home in the end, were he and Al still friends?
A proverb that is used to imply that you have unexpectedly faced a big problem
In musical terms, what properties are varied by the human voice to produce different words / syllables?
Can an iPhone 7 be made to function as a NFC Tag?
Monty Hall Problem-Probability Paradox
Why do early math courses focus on the cross sections of a cone and not on other 3D objects?
Putting class ranking in CV, but against dept guidelines
Why is std::move not [[nodiscard]] in C++20?
Getting out of while loop on console
Trying to understand entropy as a novice in thermodynamics
The test team as an enemy of development? And how can this be avoided?
Creating a Maybe type in Perl 6
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!How to create a new object instance from a TypeWhat are POD types in C++?What's the canonical way to check for type in Python?How to determine a Python variable's type?What are the differences between type() and isinstance()?How to check if type of a variable is string?Change data type of columns in PandasMaybe types in DWhy does constraining a Perl 6 named parameter to a definite value make it a required value?Are typed signatures for stubbed methods not enforced in roles for Perl6?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I have a lot of functions that can fail, but also have a return type defined in their signature. Since I like defining the types of variables whenever possible, I want to define a Maybe subset to use for this. What I came up with is this:
subset Maybe is export of Mu where Mu | Failure;
The problem with this is Failure is a subclass of Mu, so this will match anything and everything, when what I really want is to be able to match one specific type along with Failure dynamically. My next thought was to create a parameterized role to use as a type, since I don't want to create subsets for every single type that could also be a Failure. I imagine it looking something like this:
role Maybe[::T]
# ...
sub foo(--> Int) rand < 0.5 ?? 1 !! fail 'oops'
my Maybe[Int] $foo = foo;
Only I have no clue what I'd need to add to the role in order to make this work. Is it possible to create a role like this? If not, is there another way I could create a type to do what I want?
types perl6 raku
add a comment |
I have a lot of functions that can fail, but also have a return type defined in their signature. Since I like defining the types of variables whenever possible, I want to define a Maybe subset to use for this. What I came up with is this:
subset Maybe is export of Mu where Mu | Failure;
The problem with this is Failure is a subclass of Mu, so this will match anything and everything, when what I really want is to be able to match one specific type along with Failure dynamically. My next thought was to create a parameterized role to use as a type, since I don't want to create subsets for every single type that could also be a Failure. I imagine it looking something like this:
role Maybe[::T]
# ...
sub foo(--> Int) rand < 0.5 ?? 1 !! fail 'oops'
my Maybe[Int] $foo = foo;
Only I have no clue what I'd need to add to the role in order to make this work. Is it possible to create a role like this? If not, is there another way I could create a type to do what I want?
types perl6 raku
add a comment |
I have a lot of functions that can fail, but also have a return type defined in their signature. Since I like defining the types of variables whenever possible, I want to define a Maybe subset to use for this. What I came up with is this:
subset Maybe is export of Mu where Mu | Failure;
The problem with this is Failure is a subclass of Mu, so this will match anything and everything, when what I really want is to be able to match one specific type along with Failure dynamically. My next thought was to create a parameterized role to use as a type, since I don't want to create subsets for every single type that could also be a Failure. I imagine it looking something like this:
role Maybe[::T]
# ...
sub foo(--> Int) rand < 0.5 ?? 1 !! fail 'oops'
my Maybe[Int] $foo = foo;
Only I have no clue what I'd need to add to the role in order to make this work. Is it possible to create a role like this? If not, is there another way I could create a type to do what I want?
types perl6 raku
I have a lot of functions that can fail, but also have a return type defined in their signature. Since I like defining the types of variables whenever possible, I want to define a Maybe subset to use for this. What I came up with is this:
subset Maybe is export of Mu where Mu | Failure;
The problem with this is Failure is a subclass of Mu, so this will match anything and everything, when what I really want is to be able to match one specific type along with Failure dynamically. My next thought was to create a parameterized role to use as a type, since I don't want to create subsets for every single type that could also be a Failure. I imagine it looking something like this:
role Maybe[::T]
# ...
sub foo(--> Int) rand < 0.5 ?? 1 !! fail 'oops'
my Maybe[Int] $foo = foo;
Only I have no clue what I'd need to add to the role in order to make this work. Is it possible to create a role like this? If not, is there another way I could create a type to do what I want?
types perl6 raku
types perl6 raku
asked Mar 8 at 23:05
KaiepiKaiepi
694112
694112
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
Perl6 types are already Maybe types.
It's just that Perl6 has typed nulls unlike most other languages with Maybe types.
This is Maybe[Int] variable:
my Int $a;
my Int:_ $a; # more explicit
This holds a definite Int:
my Int:D $a = …; # must be assigned because the default is not “definite”
This holds a null Int:
my Int:U $a;
Note that Failure is a subtype of Nil, so even subroutines that have a return type specified can return them.
(Nil is not like null or nil from other languages.)
sub foo ( --> Int:D ) Bool.pick ?? 1 !! fail 'oops'
my $foo = foo; # $foo contains the failure object
Nil is really a type of generic soft failure. When assigned to a variable it just resets it to the default.
my Int $foo = 1;
$foo = Nil;
say $foo.perl; # Int
my Int:D $bar is default(42) = 1;
$bar = Nil
say $bar.perl; # 42
The typical default is the same as the type.
my Int $foo;
say $foo.VAR.default.perl; # Int
A specific soft failure would be to return a type object
sub foo ( --> Int )
Bool.pick ?? 1 !! Int
That is why I said Nil is a “generic” soft failure.
Generally if you are defining the type of a variable, you want it to be of that type. So your code should complain immediately if it gets something of another type.
There are better ways to deal with a Failure.
sub foo(--> Int:D ) rand < 0.5 ?? 1 !! fail 'oops'
with foo() -> Int:D $foo
… # use $foo here
else -> $fail
… # use $fail here
This works because Failure always sees itself as being undefined.
You can also use that with when
given foo()
when Int:D -> Int:D $foo
… # use $foo here
when Failure:D -> Failure:D $fail
# a DEFINITE Failure value
# (`DEFINITE` is different than `defined`.)
default
… # handle unexpected values (can be removed if not needed)
Or just the defined-or operator // if you don't care what kind of failure it is.
my Int:D $foo = foo() // 1;
You may even want to use that to turn a Failure into a Nil.
my Int:D $foo is default(42) = foo() // Nil;
If you really want a maybe-failure subset, I think this should work:
sub Maybe-Failure ( Any:U ::Type ) Failure
my constant Maybe-Int = Maybe-Failure(Int);
# note that the type has to be known at compile-time for this line:
my Maybe-Int $foo = foo;
It doesn't currently work though.
(Note that you should not be dealing with Mu unless you need to specifically deal with the types and values that are outside of the Any type; like Junction and IterationEnd.)
Something else that should probably also work is:
my class Maybe-Failure
method ^parameterize ( $, Any:U ::Type )
anon subset :: of Any where Type
my Maybe-Failure[Int] $foo;
This seems like it fails for the same reason the other one does.
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
This is a good explanation of different ways to deal with failures, but I was looking for a way to define a type for what may be aFailurethat I could use when assignin the return value of a function that can fail to a variable before handling it properly. That way, my code could be a little more terse
– Kaiepi
Mar 9 at 22:43
add a comment |
TL;DR See @Kaiepi's own answer for a solution. But every non-native type in P6 is already automatically an enhanced nullable type that's akin to an enhanced Maybe type. So that needs to be discussed too. To help structure my answer I'm going to pretend it's an XY problem even though it isn't.
Solving Y
I want to define a
Maybe subsetto use for this
See @Kaiepi's answer.
All non-native P6 types are already akin to Maybe types
The subset solution is overkill for what wikipedia defines as a Maybe type which boils down to:
None[or] the original data type
It turns out that all non-native P6 types are already something akin to an enhanced Maybe type.
The enhancement is that the (P6 equivalent of a) None knows what original data type it's been paired with:
my Int $foo;
say $foo # (Int) -- akin to an (Int) None
Solving X
I have a lot of functions that can fail, but also have a return type defined in their signature.
As you presumably know, unless use fatal; is in effect, P6 deliberately allows routines to return failures even if there's a return type check that doesn't explicitly allow them. (A subset return type check can explicitly reject them.)
So given that a return type check Foo is automatically turned into something akin to a subset with a where Failure | Foo clause, it's understandable that you thought to accommodate that by creating an matching subset so you could accept the result when assigning to a variable.
But as is hopefully clear from the earlier discussion, it may be better to make use of the built in aspect of P6's type system that's akin to Maybe types.
A Nil may be used to indicate what's called a benign failure. So the following works to indicate failure (as you wish to do in some of your routines) and set a receiving variable to a None (or rather the enhanced P6 equivalent of one):
sub foo (--> Int) Nil
my Int $bar = foo;
say $bar; # (Int)
So one option is that you replace calls to fail with return Nil (or just Nil).
One could imagine a pragma (called, say, failsoft) that demotes all Failures to benign failure Nils:
use failsoft;
sub foo (--> Int) fail
my Int $bar = foo;
say $bar; # (Int)
Nullable types
The wikipedia introduction about Maybe types also says:
A distinct, but related concept ... is called nullable types (often expressed as
A?).
The closest P6 equivalent to the Int? syntax used by some languages to express a nullable Int is simply Int, without the question mark. The following are valid type constraints:
Int-- P6 equivalent of a nullableIntor aMaybe IntInt:D-- P6 equivalent of a non-nullableIntor aJust IntInt:U-- P6 equivalent of anIntnull or an(Int) None
(:D and :U are called type smilies for an obvious reason. :))
Continuing, wikipedia's Nullable types page says:
In statically-typed languages, a nullable type is [a Maybe] type (in functional programming terms), while in dynamically-typed languages (where values have types, but variables do not), equivalent behavior is provided by having a single null value.
In P6:
Values have types -- but so do variables.
P6 types are akin to an enhanced
Maybetype (as explained above) or an enhanced nullable type where there are as manyNones or "null" values as there are types instead of having just a singleNoneor null value.
(So, is P6 a statically typed language or a dynamically typed language? It's actually Beyond static vs dynamic and is instead static and dynamic.)
Continuing:
Primitive types such as integers and booleans cannot generally be null, but the corresponding nullable types (nullable integer and nullable boolean, respectively) can also assume the
NULLvalue.
In P6, all non-native types (like the arbitrary precision Int type) are akin to enhanced Maybe/nullable types.
In contrast, all native types (like int -- all lowercase) are non-nullable types -- what wikipedia is calling primitive types. They cannot be null or None:
my int $foo;
say $foo; # 0
$foo = int; # Cannot unbox a type object (int) to int
Finally, returning to the wikipedia Maybe page:
The core difference between [maybe] types and nullable types is that [maybe] types support nesting
(Maybe (Maybe A) ≠ Maybe A), while nullable types do not(A?? = A?).
P6's built in types don't support nesting in this way without use of subsets. So a P6 type, while akin to an enhanced Maybe type, is really just an enhanced nullable type.
Good point about what I was callingMaybenot actually beingMaybeby definition
– Kaiepi
Mar 9 at 23:35
I think the explanation's better now. With the Solving X section, while I can see how returningNilwould be better than failing in certain cases, for what I was writing when I asked the question it doesn't. I use failure messages to notify users of the program when something goes wrong, and for some routines, I let their exception get thrown in certain places they're used when failing is unacceptable, but not for other places where it'd make more sense to deal with them in other ways.
– Kaiepi
Mar 14 at 9:43
add a comment |
Brad Gilbert's answer pointed me in the right direction, particularly:
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
The solution I came up with is this:
use nqp;
class Maybe
method ^parameterize(Mu:U M, Mu:U T) Failure)
my Maybe[Int] $foo = 1;
say $foo; # OUTPUT: 1
my Maybe[Int] $bar = Failure.new: 2;
say $bar.exception.message; # OUTPUT: 2
my Maybe[Int] $baz = 'qux'; # Throws type error
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55072228%2fcreating-a-maybe-type-in-perl-6%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Perl6 types are already Maybe types.
It's just that Perl6 has typed nulls unlike most other languages with Maybe types.
This is Maybe[Int] variable:
my Int $a;
my Int:_ $a; # more explicit
This holds a definite Int:
my Int:D $a = …; # must be assigned because the default is not “definite”
This holds a null Int:
my Int:U $a;
Note that Failure is a subtype of Nil, so even subroutines that have a return type specified can return them.
(Nil is not like null or nil from other languages.)
sub foo ( --> Int:D ) Bool.pick ?? 1 !! fail 'oops'
my $foo = foo; # $foo contains the failure object
Nil is really a type of generic soft failure. When assigned to a variable it just resets it to the default.
my Int $foo = 1;
$foo = Nil;
say $foo.perl; # Int
my Int:D $bar is default(42) = 1;
$bar = Nil
say $bar.perl; # 42
The typical default is the same as the type.
my Int $foo;
say $foo.VAR.default.perl; # Int
A specific soft failure would be to return a type object
sub foo ( --> Int )
Bool.pick ?? 1 !! Int
That is why I said Nil is a “generic” soft failure.
Generally if you are defining the type of a variable, you want it to be of that type. So your code should complain immediately if it gets something of another type.
There are better ways to deal with a Failure.
sub foo(--> Int:D ) rand < 0.5 ?? 1 !! fail 'oops'
with foo() -> Int:D $foo
… # use $foo here
else -> $fail
… # use $fail here
This works because Failure always sees itself as being undefined.
You can also use that with when
given foo()
when Int:D -> Int:D $foo
… # use $foo here
when Failure:D -> Failure:D $fail
# a DEFINITE Failure value
# (`DEFINITE` is different than `defined`.)
default
… # handle unexpected values (can be removed if not needed)
Or just the defined-or operator // if you don't care what kind of failure it is.
my Int:D $foo = foo() // 1;
You may even want to use that to turn a Failure into a Nil.
my Int:D $foo is default(42) = foo() // Nil;
If you really want a maybe-failure subset, I think this should work:
sub Maybe-Failure ( Any:U ::Type ) Failure
my constant Maybe-Int = Maybe-Failure(Int);
# note that the type has to be known at compile-time for this line:
my Maybe-Int $foo = foo;
It doesn't currently work though.
(Note that you should not be dealing with Mu unless you need to specifically deal with the types and values that are outside of the Any type; like Junction and IterationEnd.)
Something else that should probably also work is:
my class Maybe-Failure
method ^parameterize ( $, Any:U ::Type )
anon subset :: of Any where Type
my Maybe-Failure[Int] $foo;
This seems like it fails for the same reason the other one does.
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
This is a good explanation of different ways to deal with failures, but I was looking for a way to define a type for what may be aFailurethat I could use when assignin the return value of a function that can fail to a variable before handling it properly. That way, my code could be a little more terse
– Kaiepi
Mar 9 at 22:43
add a comment |
Perl6 types are already Maybe types.
It's just that Perl6 has typed nulls unlike most other languages with Maybe types.
This is Maybe[Int] variable:
my Int $a;
my Int:_ $a; # more explicit
This holds a definite Int:
my Int:D $a = …; # must be assigned because the default is not “definite”
This holds a null Int:
my Int:U $a;
Note that Failure is a subtype of Nil, so even subroutines that have a return type specified can return them.
(Nil is not like null or nil from other languages.)
sub foo ( --> Int:D ) Bool.pick ?? 1 !! fail 'oops'
my $foo = foo; # $foo contains the failure object
Nil is really a type of generic soft failure. When assigned to a variable it just resets it to the default.
my Int $foo = 1;
$foo = Nil;
say $foo.perl; # Int
my Int:D $bar is default(42) = 1;
$bar = Nil
say $bar.perl; # 42
The typical default is the same as the type.
my Int $foo;
say $foo.VAR.default.perl; # Int
A specific soft failure would be to return a type object
sub foo ( --> Int )
Bool.pick ?? 1 !! Int
That is why I said Nil is a “generic” soft failure.
Generally if you are defining the type of a variable, you want it to be of that type. So your code should complain immediately if it gets something of another type.
There are better ways to deal with a Failure.
sub foo(--> Int:D ) rand < 0.5 ?? 1 !! fail 'oops'
with foo() -> Int:D $foo
… # use $foo here
else -> $fail
… # use $fail here
This works because Failure always sees itself as being undefined.
You can also use that with when
given foo()
when Int:D -> Int:D $foo
… # use $foo here
when Failure:D -> Failure:D $fail
# a DEFINITE Failure value
# (`DEFINITE` is different than `defined`.)
default
… # handle unexpected values (can be removed if not needed)
Or just the defined-or operator // if you don't care what kind of failure it is.
my Int:D $foo = foo() // 1;
You may even want to use that to turn a Failure into a Nil.
my Int:D $foo is default(42) = foo() // Nil;
If you really want a maybe-failure subset, I think this should work:
sub Maybe-Failure ( Any:U ::Type ) Failure
my constant Maybe-Int = Maybe-Failure(Int);
# note that the type has to be known at compile-time for this line:
my Maybe-Int $foo = foo;
It doesn't currently work though.
(Note that you should not be dealing with Mu unless you need to specifically deal with the types and values that are outside of the Any type; like Junction and IterationEnd.)
Something else that should probably also work is:
my class Maybe-Failure
method ^parameterize ( $, Any:U ::Type )
anon subset :: of Any where Type
my Maybe-Failure[Int] $foo;
This seems like it fails for the same reason the other one does.
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
This is a good explanation of different ways to deal with failures, but I was looking for a way to define a type for what may be aFailurethat I could use when assignin the return value of a function that can fail to a variable before handling it properly. That way, my code could be a little more terse
– Kaiepi
Mar 9 at 22:43
add a comment |
Perl6 types are already Maybe types.
It's just that Perl6 has typed nulls unlike most other languages with Maybe types.
This is Maybe[Int] variable:
my Int $a;
my Int:_ $a; # more explicit
This holds a definite Int:
my Int:D $a = …; # must be assigned because the default is not “definite”
This holds a null Int:
my Int:U $a;
Note that Failure is a subtype of Nil, so even subroutines that have a return type specified can return them.
(Nil is not like null or nil from other languages.)
sub foo ( --> Int:D ) Bool.pick ?? 1 !! fail 'oops'
my $foo = foo; # $foo contains the failure object
Nil is really a type of generic soft failure. When assigned to a variable it just resets it to the default.
my Int $foo = 1;
$foo = Nil;
say $foo.perl; # Int
my Int:D $bar is default(42) = 1;
$bar = Nil
say $bar.perl; # 42
The typical default is the same as the type.
my Int $foo;
say $foo.VAR.default.perl; # Int
A specific soft failure would be to return a type object
sub foo ( --> Int )
Bool.pick ?? 1 !! Int
That is why I said Nil is a “generic” soft failure.
Generally if you are defining the type of a variable, you want it to be of that type. So your code should complain immediately if it gets something of another type.
There are better ways to deal with a Failure.
sub foo(--> Int:D ) rand < 0.5 ?? 1 !! fail 'oops'
with foo() -> Int:D $foo
… # use $foo here
else -> $fail
… # use $fail here
This works because Failure always sees itself as being undefined.
You can also use that with when
given foo()
when Int:D -> Int:D $foo
… # use $foo here
when Failure:D -> Failure:D $fail
# a DEFINITE Failure value
# (`DEFINITE` is different than `defined`.)
default
… # handle unexpected values (can be removed if not needed)
Or just the defined-or operator // if you don't care what kind of failure it is.
my Int:D $foo = foo() // 1;
You may even want to use that to turn a Failure into a Nil.
my Int:D $foo is default(42) = foo() // Nil;
If you really want a maybe-failure subset, I think this should work:
sub Maybe-Failure ( Any:U ::Type ) Failure
my constant Maybe-Int = Maybe-Failure(Int);
# note that the type has to be known at compile-time for this line:
my Maybe-Int $foo = foo;
It doesn't currently work though.
(Note that you should not be dealing with Mu unless you need to specifically deal with the types and values that are outside of the Any type; like Junction and IterationEnd.)
Something else that should probably also work is:
my class Maybe-Failure
method ^parameterize ( $, Any:U ::Type )
anon subset :: of Any where Type
my Maybe-Failure[Int] $foo;
This seems like it fails for the same reason the other one does.
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
Perl6 types are already Maybe types.
It's just that Perl6 has typed nulls unlike most other languages with Maybe types.
This is Maybe[Int] variable:
my Int $a;
my Int:_ $a; # more explicit
This holds a definite Int:
my Int:D $a = …; # must be assigned because the default is not “definite”
This holds a null Int:
my Int:U $a;
Note that Failure is a subtype of Nil, so even subroutines that have a return type specified can return them.
(Nil is not like null or nil from other languages.)
sub foo ( --> Int:D ) Bool.pick ?? 1 !! fail 'oops'
my $foo = foo; # $foo contains the failure object
Nil is really a type of generic soft failure. When assigned to a variable it just resets it to the default.
my Int $foo = 1;
$foo = Nil;
say $foo.perl; # Int
my Int:D $bar is default(42) = 1;
$bar = Nil
say $bar.perl; # 42
The typical default is the same as the type.
my Int $foo;
say $foo.VAR.default.perl; # Int
A specific soft failure would be to return a type object
sub foo ( --> Int )
Bool.pick ?? 1 !! Int
That is why I said Nil is a “generic” soft failure.
Generally if you are defining the type of a variable, you want it to be of that type. So your code should complain immediately if it gets something of another type.
There are better ways to deal with a Failure.
sub foo(--> Int:D ) rand < 0.5 ?? 1 !! fail 'oops'
with foo() -> Int:D $foo
… # use $foo here
else -> $fail
… # use $fail here
This works because Failure always sees itself as being undefined.
You can also use that with when
given foo()
when Int:D -> Int:D $foo
… # use $foo here
when Failure:D -> Failure:D $fail
# a DEFINITE Failure value
# (`DEFINITE` is different than `defined`.)
default
… # handle unexpected values (can be removed if not needed)
Or just the defined-or operator // if you don't care what kind of failure it is.
my Int:D $foo = foo() // 1;
You may even want to use that to turn a Failure into a Nil.
my Int:D $foo is default(42) = foo() // Nil;
If you really want a maybe-failure subset, I think this should work:
sub Maybe-Failure ( Any:U ::Type ) Failure
my constant Maybe-Int = Maybe-Failure(Int);
# note that the type has to be known at compile-time for this line:
my Maybe-Int $foo = foo;
It doesn't currently work though.
(Note that you should not be dealing with Mu unless you need to specifically deal with the types and values that are outside of the Any type; like Junction and IterationEnd.)
Something else that should probably also work is:
my class Maybe-Failure
method ^parameterize ( $, Any:U ::Type )
anon subset :: of Any where Type
my Maybe-Failure[Int] $foo;
This seems like it fails for the same reason the other one does.
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
edited Mar 9 at 22:40
ugexe
2,7561529
2,7561529
answered Mar 9 at 17:03
Brad GilbertBrad Gilbert
26.2k866112
26.2k866112
This is a good explanation of different ways to deal with failures, but I was looking for a way to define a type for what may be aFailurethat I could use when assignin the return value of a function that can fail to a variable before handling it properly. That way, my code could be a little more terse
– Kaiepi
Mar 9 at 22:43
add a comment |
This is a good explanation of different ways to deal with failures, but I was looking for a way to define a type for what may be aFailurethat I could use when assignin the return value of a function that can fail to a variable before handling it properly. That way, my code could be a little more terse
– Kaiepi
Mar 9 at 22:43
This is a good explanation of different ways to deal with failures, but I was looking for a way to define a type for what may be a
Failure that I could use when assignin the return value of a function that can fail to a variable before handling it properly. That way, my code could be a little more terse– Kaiepi
Mar 9 at 22:43
This is a good explanation of different ways to deal with failures, but I was looking for a way to define a type for what may be a
Failure that I could use when assignin the return value of a function that can fail to a variable before handling it properly. That way, my code could be a little more terse– Kaiepi
Mar 9 at 22:43
add a comment |
TL;DR See @Kaiepi's own answer for a solution. But every non-native type in P6 is already automatically an enhanced nullable type that's akin to an enhanced Maybe type. So that needs to be discussed too. To help structure my answer I'm going to pretend it's an XY problem even though it isn't.
Solving Y
I want to define a
Maybe subsetto use for this
See @Kaiepi's answer.
All non-native P6 types are already akin to Maybe types
The subset solution is overkill for what wikipedia defines as a Maybe type which boils down to:
None[or] the original data type
It turns out that all non-native P6 types are already something akin to an enhanced Maybe type.
The enhancement is that the (P6 equivalent of a) None knows what original data type it's been paired with:
my Int $foo;
say $foo # (Int) -- akin to an (Int) None
Solving X
I have a lot of functions that can fail, but also have a return type defined in their signature.
As you presumably know, unless use fatal; is in effect, P6 deliberately allows routines to return failures even if there's a return type check that doesn't explicitly allow them. (A subset return type check can explicitly reject them.)
So given that a return type check Foo is automatically turned into something akin to a subset with a where Failure | Foo clause, it's understandable that you thought to accommodate that by creating an matching subset so you could accept the result when assigning to a variable.
But as is hopefully clear from the earlier discussion, it may be better to make use of the built in aspect of P6's type system that's akin to Maybe types.
A Nil may be used to indicate what's called a benign failure. So the following works to indicate failure (as you wish to do in some of your routines) and set a receiving variable to a None (or rather the enhanced P6 equivalent of one):
sub foo (--> Int) Nil
my Int $bar = foo;
say $bar; # (Int)
So one option is that you replace calls to fail with return Nil (or just Nil).
One could imagine a pragma (called, say, failsoft) that demotes all Failures to benign failure Nils:
use failsoft;
sub foo (--> Int) fail
my Int $bar = foo;
say $bar; # (Int)
Nullable types
The wikipedia introduction about Maybe types also says:
A distinct, but related concept ... is called nullable types (often expressed as
A?).
The closest P6 equivalent to the Int? syntax used by some languages to express a nullable Int is simply Int, without the question mark. The following are valid type constraints:
Int-- P6 equivalent of a nullableIntor aMaybe IntInt:D-- P6 equivalent of a non-nullableIntor aJust IntInt:U-- P6 equivalent of anIntnull or an(Int) None
(:D and :U are called type smilies for an obvious reason. :))
Continuing, wikipedia's Nullable types page says:
In statically-typed languages, a nullable type is [a Maybe] type (in functional programming terms), while in dynamically-typed languages (where values have types, but variables do not), equivalent behavior is provided by having a single null value.
In P6:
Values have types -- but so do variables.
P6 types are akin to an enhanced
Maybetype (as explained above) or an enhanced nullable type where there are as manyNones or "null" values as there are types instead of having just a singleNoneor null value.
(So, is P6 a statically typed language or a dynamically typed language? It's actually Beyond static vs dynamic and is instead static and dynamic.)
Continuing:
Primitive types such as integers and booleans cannot generally be null, but the corresponding nullable types (nullable integer and nullable boolean, respectively) can also assume the
NULLvalue.
In P6, all non-native types (like the arbitrary precision Int type) are akin to enhanced Maybe/nullable types.
In contrast, all native types (like int -- all lowercase) are non-nullable types -- what wikipedia is calling primitive types. They cannot be null or None:
my int $foo;
say $foo; # 0
$foo = int; # Cannot unbox a type object (int) to int
Finally, returning to the wikipedia Maybe page:
The core difference between [maybe] types and nullable types is that [maybe] types support nesting
(Maybe (Maybe A) ≠ Maybe A), while nullable types do not(A?? = A?).
P6's built in types don't support nesting in this way without use of subsets. So a P6 type, while akin to an enhanced Maybe type, is really just an enhanced nullable type.
Good point about what I was callingMaybenot actually beingMaybeby definition
– Kaiepi
Mar 9 at 23:35
I think the explanation's better now. With the Solving X section, while I can see how returningNilwould be better than failing in certain cases, for what I was writing when I asked the question it doesn't. I use failure messages to notify users of the program when something goes wrong, and for some routines, I let their exception get thrown in certain places they're used when failing is unacceptable, but not for other places where it'd make more sense to deal with them in other ways.
– Kaiepi
Mar 14 at 9:43
add a comment |
TL;DR See @Kaiepi's own answer for a solution. But every non-native type in P6 is already automatically an enhanced nullable type that's akin to an enhanced Maybe type. So that needs to be discussed too. To help structure my answer I'm going to pretend it's an XY problem even though it isn't.
Solving Y
I want to define a
Maybe subsetto use for this
See @Kaiepi's answer.
All non-native P6 types are already akin to Maybe types
The subset solution is overkill for what wikipedia defines as a Maybe type which boils down to:
None[or] the original data type
It turns out that all non-native P6 types are already something akin to an enhanced Maybe type.
The enhancement is that the (P6 equivalent of a) None knows what original data type it's been paired with:
my Int $foo;
say $foo # (Int) -- akin to an (Int) None
Solving X
I have a lot of functions that can fail, but also have a return type defined in their signature.
As you presumably know, unless use fatal; is in effect, P6 deliberately allows routines to return failures even if there's a return type check that doesn't explicitly allow them. (A subset return type check can explicitly reject them.)
So given that a return type check Foo is automatically turned into something akin to a subset with a where Failure | Foo clause, it's understandable that you thought to accommodate that by creating an matching subset so you could accept the result when assigning to a variable.
But as is hopefully clear from the earlier discussion, it may be better to make use of the built in aspect of P6's type system that's akin to Maybe types.
A Nil may be used to indicate what's called a benign failure. So the following works to indicate failure (as you wish to do in some of your routines) and set a receiving variable to a None (or rather the enhanced P6 equivalent of one):
sub foo (--> Int) Nil
my Int $bar = foo;
say $bar; # (Int)
So one option is that you replace calls to fail with return Nil (or just Nil).
One could imagine a pragma (called, say, failsoft) that demotes all Failures to benign failure Nils:
use failsoft;
sub foo (--> Int) fail
my Int $bar = foo;
say $bar; # (Int)
Nullable types
The wikipedia introduction about Maybe types also says:
A distinct, but related concept ... is called nullable types (often expressed as
A?).
The closest P6 equivalent to the Int? syntax used by some languages to express a nullable Int is simply Int, without the question mark. The following are valid type constraints:
Int-- P6 equivalent of a nullableIntor aMaybe IntInt:D-- P6 equivalent of a non-nullableIntor aJust IntInt:U-- P6 equivalent of anIntnull or an(Int) None
(:D and :U are called type smilies for an obvious reason. :))
Continuing, wikipedia's Nullable types page says:
In statically-typed languages, a nullable type is [a Maybe] type (in functional programming terms), while in dynamically-typed languages (where values have types, but variables do not), equivalent behavior is provided by having a single null value.
In P6:
Values have types -- but so do variables.
P6 types are akin to an enhanced
Maybetype (as explained above) or an enhanced nullable type where there are as manyNones or "null" values as there are types instead of having just a singleNoneor null value.
(So, is P6 a statically typed language or a dynamically typed language? It's actually Beyond static vs dynamic and is instead static and dynamic.)
Continuing:
Primitive types such as integers and booleans cannot generally be null, but the corresponding nullable types (nullable integer and nullable boolean, respectively) can also assume the
NULLvalue.
In P6, all non-native types (like the arbitrary precision Int type) are akin to enhanced Maybe/nullable types.
In contrast, all native types (like int -- all lowercase) are non-nullable types -- what wikipedia is calling primitive types. They cannot be null or None:
my int $foo;
say $foo; # 0
$foo = int; # Cannot unbox a type object (int) to int
Finally, returning to the wikipedia Maybe page:
The core difference between [maybe] types and nullable types is that [maybe] types support nesting
(Maybe (Maybe A) ≠ Maybe A), while nullable types do not(A?? = A?).
P6's built in types don't support nesting in this way without use of subsets. So a P6 type, while akin to an enhanced Maybe type, is really just an enhanced nullable type.
Good point about what I was callingMaybenot actually beingMaybeby definition
– Kaiepi
Mar 9 at 23:35
I think the explanation's better now. With the Solving X section, while I can see how returningNilwould be better than failing in certain cases, for what I was writing when I asked the question it doesn't. I use failure messages to notify users of the program when something goes wrong, and for some routines, I let their exception get thrown in certain places they're used when failing is unacceptable, but not for other places where it'd make more sense to deal with them in other ways.
– Kaiepi
Mar 14 at 9:43
add a comment |
TL;DR See @Kaiepi's own answer for a solution. But every non-native type in P6 is already automatically an enhanced nullable type that's akin to an enhanced Maybe type. So that needs to be discussed too. To help structure my answer I'm going to pretend it's an XY problem even though it isn't.
Solving Y
I want to define a
Maybe subsetto use for this
See @Kaiepi's answer.
All non-native P6 types are already akin to Maybe types
The subset solution is overkill for what wikipedia defines as a Maybe type which boils down to:
None[or] the original data type
It turns out that all non-native P6 types are already something akin to an enhanced Maybe type.
The enhancement is that the (P6 equivalent of a) None knows what original data type it's been paired with:
my Int $foo;
say $foo # (Int) -- akin to an (Int) None
Solving X
I have a lot of functions that can fail, but also have a return type defined in their signature.
As you presumably know, unless use fatal; is in effect, P6 deliberately allows routines to return failures even if there's a return type check that doesn't explicitly allow them. (A subset return type check can explicitly reject them.)
So given that a return type check Foo is automatically turned into something akin to a subset with a where Failure | Foo clause, it's understandable that you thought to accommodate that by creating an matching subset so you could accept the result when assigning to a variable.
But as is hopefully clear from the earlier discussion, it may be better to make use of the built in aspect of P6's type system that's akin to Maybe types.
A Nil may be used to indicate what's called a benign failure. So the following works to indicate failure (as you wish to do in some of your routines) and set a receiving variable to a None (or rather the enhanced P6 equivalent of one):
sub foo (--> Int) Nil
my Int $bar = foo;
say $bar; # (Int)
So one option is that you replace calls to fail with return Nil (or just Nil).
One could imagine a pragma (called, say, failsoft) that demotes all Failures to benign failure Nils:
use failsoft;
sub foo (--> Int) fail
my Int $bar = foo;
say $bar; # (Int)
Nullable types
The wikipedia introduction about Maybe types also says:
A distinct, but related concept ... is called nullable types (often expressed as
A?).
The closest P6 equivalent to the Int? syntax used by some languages to express a nullable Int is simply Int, without the question mark. The following are valid type constraints:
Int-- P6 equivalent of a nullableIntor aMaybe IntInt:D-- P6 equivalent of a non-nullableIntor aJust IntInt:U-- P6 equivalent of anIntnull or an(Int) None
(:D and :U are called type smilies for an obvious reason. :))
Continuing, wikipedia's Nullable types page says:
In statically-typed languages, a nullable type is [a Maybe] type (in functional programming terms), while in dynamically-typed languages (where values have types, but variables do not), equivalent behavior is provided by having a single null value.
In P6:
Values have types -- but so do variables.
P6 types are akin to an enhanced
Maybetype (as explained above) or an enhanced nullable type where there are as manyNones or "null" values as there are types instead of having just a singleNoneor null value.
(So, is P6 a statically typed language or a dynamically typed language? It's actually Beyond static vs dynamic and is instead static and dynamic.)
Continuing:
Primitive types such as integers and booleans cannot generally be null, but the corresponding nullable types (nullable integer and nullable boolean, respectively) can also assume the
NULLvalue.
In P6, all non-native types (like the arbitrary precision Int type) are akin to enhanced Maybe/nullable types.
In contrast, all native types (like int -- all lowercase) are non-nullable types -- what wikipedia is calling primitive types. They cannot be null or None:
my int $foo;
say $foo; # 0
$foo = int; # Cannot unbox a type object (int) to int
Finally, returning to the wikipedia Maybe page:
The core difference between [maybe] types and nullable types is that [maybe] types support nesting
(Maybe (Maybe A) ≠ Maybe A), while nullable types do not(A?? = A?).
P6's built in types don't support nesting in this way without use of subsets. So a P6 type, while akin to an enhanced Maybe type, is really just an enhanced nullable type.
TL;DR See @Kaiepi's own answer for a solution. But every non-native type in P6 is already automatically an enhanced nullable type that's akin to an enhanced Maybe type. So that needs to be discussed too. To help structure my answer I'm going to pretend it's an XY problem even though it isn't.
Solving Y
I want to define a
Maybe subsetto use for this
See @Kaiepi's answer.
All non-native P6 types are already akin to Maybe types
The subset solution is overkill for what wikipedia defines as a Maybe type which boils down to:
None[or] the original data type
It turns out that all non-native P6 types are already something akin to an enhanced Maybe type.
The enhancement is that the (P6 equivalent of a) None knows what original data type it's been paired with:
my Int $foo;
say $foo # (Int) -- akin to an (Int) None
Solving X
I have a lot of functions that can fail, but also have a return type defined in their signature.
As you presumably know, unless use fatal; is in effect, P6 deliberately allows routines to return failures even if there's a return type check that doesn't explicitly allow them. (A subset return type check can explicitly reject them.)
So given that a return type check Foo is automatically turned into something akin to a subset with a where Failure | Foo clause, it's understandable that you thought to accommodate that by creating an matching subset so you could accept the result when assigning to a variable.
But as is hopefully clear from the earlier discussion, it may be better to make use of the built in aspect of P6's type system that's akin to Maybe types.
A Nil may be used to indicate what's called a benign failure. So the following works to indicate failure (as you wish to do in some of your routines) and set a receiving variable to a None (or rather the enhanced P6 equivalent of one):
sub foo (--> Int) Nil
my Int $bar = foo;
say $bar; # (Int)
So one option is that you replace calls to fail with return Nil (or just Nil).
One could imagine a pragma (called, say, failsoft) that demotes all Failures to benign failure Nils:
use failsoft;
sub foo (--> Int) fail
my Int $bar = foo;
say $bar; # (Int)
Nullable types
The wikipedia introduction about Maybe types also says:
A distinct, but related concept ... is called nullable types (often expressed as
A?).
The closest P6 equivalent to the Int? syntax used by some languages to express a nullable Int is simply Int, without the question mark. The following are valid type constraints:
Int-- P6 equivalent of a nullableIntor aMaybe IntInt:D-- P6 equivalent of a non-nullableIntor aJust IntInt:U-- P6 equivalent of anIntnull or an(Int) None
(:D and :U are called type smilies for an obvious reason. :))
Continuing, wikipedia's Nullable types page says:
In statically-typed languages, a nullable type is [a Maybe] type (in functional programming terms), while in dynamically-typed languages (where values have types, but variables do not), equivalent behavior is provided by having a single null value.
In P6:
Values have types -- but so do variables.
P6 types are akin to an enhanced
Maybetype (as explained above) or an enhanced nullable type where there are as manyNones or "null" values as there are types instead of having just a singleNoneor null value.
(So, is P6 a statically typed language or a dynamically typed language? It's actually Beyond static vs dynamic and is instead static and dynamic.)
Continuing:
Primitive types such as integers and booleans cannot generally be null, but the corresponding nullable types (nullable integer and nullable boolean, respectively) can also assume the
NULLvalue.
In P6, all non-native types (like the arbitrary precision Int type) are akin to enhanced Maybe/nullable types.
In contrast, all native types (like int -- all lowercase) are non-nullable types -- what wikipedia is calling primitive types. They cannot be null or None:
my int $foo;
say $foo; # 0
$foo = int; # Cannot unbox a type object (int) to int
Finally, returning to the wikipedia Maybe page:
The core difference between [maybe] types and nullable types is that [maybe] types support nesting
(Maybe (Maybe A) ≠ Maybe A), while nullable types do not(A?? = A?).
P6's built in types don't support nesting in this way without use of subsets. So a P6 type, while akin to an enhanced Maybe type, is really just an enhanced nullable type.
edited Mar 11 at 22:35
answered Mar 9 at 22:45
raiphraiph
12.3k22444
12.3k22444
Good point about what I was callingMaybenot actually beingMaybeby definition
– Kaiepi
Mar 9 at 23:35
I think the explanation's better now. With the Solving X section, while I can see how returningNilwould be better than failing in certain cases, for what I was writing when I asked the question it doesn't. I use failure messages to notify users of the program when something goes wrong, and for some routines, I let their exception get thrown in certain places they're used when failing is unacceptable, but not for other places where it'd make more sense to deal with them in other ways.
– Kaiepi
Mar 14 at 9:43
add a comment |
Good point about what I was callingMaybenot actually beingMaybeby definition
– Kaiepi
Mar 9 at 23:35
I think the explanation's better now. With the Solving X section, while I can see how returningNilwould be better than failing in certain cases, for what I was writing when I asked the question it doesn't. I use failure messages to notify users of the program when something goes wrong, and for some routines, I let their exception get thrown in certain places they're used when failing is unacceptable, but not for other places where it'd make more sense to deal with them in other ways.
– Kaiepi
Mar 14 at 9:43
Good point about what I was calling
Maybe not actually being Maybe by definition– Kaiepi
Mar 9 at 23:35
Good point about what I was calling
Maybe not actually being Maybe by definition– Kaiepi
Mar 9 at 23:35
I think the explanation's better now. With the Solving X section, while I can see how returning
Nil would be better than failing in certain cases, for what I was writing when I asked the question it doesn't. I use failure messages to notify users of the program when something goes wrong, and for some routines, I let their exception get thrown in certain places they're used when failing is unacceptable, but not for other places where it'd make more sense to deal with them in other ways.– Kaiepi
Mar 14 at 9:43
I think the explanation's better now. With the Solving X section, while I can see how returning
Nil would be better than failing in certain cases, for what I was writing when I asked the question it doesn't. I use failure messages to notify users of the program when something goes wrong, and for some routines, I let their exception get thrown in certain places they're used when failing is unacceptable, but not for other places where it'd make more sense to deal with them in other ways.– Kaiepi
Mar 14 at 9:43
add a comment |
Brad Gilbert's answer pointed me in the right direction, particularly:
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
The solution I came up with is this:
use nqp;
class Maybe
method ^parameterize(Mu:U M, Mu:U T) Failure)
my Maybe[Int] $foo = 1;
say $foo; # OUTPUT: 1
my Maybe[Int] $bar = Failure.new: 2;
say $bar.exception.message; # OUTPUT: 2
my Maybe[Int] $baz = 'qux'; # Throws type error
add a comment |
Brad Gilbert's answer pointed me in the right direction, particularly:
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
The solution I came up with is this:
use nqp;
class Maybe
method ^parameterize(Mu:U M, Mu:U T) Failure)
my Maybe[Int] $foo = 1;
say $foo; # OUTPUT: 1
my Maybe[Int] $bar = Failure.new: 2;
say $bar.exception.message; # OUTPUT: 2
my Maybe[Int] $baz = 'qux'; # Throws type error
add a comment |
Brad Gilbert's answer pointed me in the right direction, particularly:
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
The solution I came up with is this:
use nqp;
class Maybe
method ^parameterize(Mu:U M, Mu:U T) Failure)
my Maybe[Int] $foo = 1;
say $foo; # OUTPUT: 1
my Maybe[Int] $bar = Failure.new: 2;
say $bar.exception.message; # OUTPUT: 2
my Maybe[Int] $baz = 'qux'; # Throws type error
Brad Gilbert's answer pointed me in the right direction, particularly:
Another way would be to create a new type of class like subset.
That is subset uses a different MOP than the rest of the classes in Perl6.
The solution I came up with is this:
use nqp;
class Maybe
method ^parameterize(Mu:U M, Mu:U T) Failure)
my Maybe[Int] $foo = 1;
say $foo; # OUTPUT: 1
my Maybe[Int] $bar = Failure.new: 2;
say $bar.exception.message; # OUTPUT: 2
my Maybe[Int] $baz = 'qux'; # Throws type error
answered Mar 9 at 22:30
KaiepiKaiepi
694112
694112
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55072228%2fcreating-a-maybe-type-in-perl-6%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown