Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FAIL native for raising an error or error-spec #87

Merged
merged 1 commit into from
Sep 11, 2015
Merged

Add FAIL native for raising an error or error-spec #87

merged 1 commit into from
Sep 11, 2015

Conversation

hostilefork
Copy link
Member

The FAIL native takes the place of DO'ing an error to raise it, and
is also able to take a STRING! or a BLOCK!. The string is sent to
MAKE ERROR! directly, while blocks are processed in a new kind of
"error creation dialect". The dialect evaluates a WORD! as long as
it does not evaluate to a function, and also will evaluate parens:

 fail ["Problem with foo:" foo "occurred at" (1 + 2)]

...this would behave equivalently to what has been written as:

do make error! form reduce [
    "problem with foo:" foo "occurred at" (1 + 2)
]

Limiting types is to faciliate the dialect becoming more expressive.
It may use SET-WORD!, TAG!, and other choices to cue the fields
and formatting template structure for the error object being returned
to TRAP. Hence those types are available for future expansion. In
the meantime, the PAREN!'s general-purpose-escape will allow
for any substitution that FORM REDUCE might otherwise achieve.

It removes a commented out prior placeholder for a FAIL-like native
that was named "CAUSE". That word may make sense when paired
directly with something like a variable named error...but as a
convenience routine that might be used with (for instance) a string it
doesn't communicate that an error has occurred and that execution
will be interrupted. (RAISE was rejected for similar reasons.)

This is planned as the replacement for DO's handling of errors. So
calling DO on an ERROR! will now still raise an error, but not the one
you asked for...rather an error directing the user to the use of FAIL.

Similarly, THROW directs users who try and pass errors to use FAIL
(as it would be a common misconception for people from other
languages to think that THROW is what you are supposed to use).
While a refinement was considered to allow throwing errors, the
rarity of the operation and the existence of workarounds (e.g. putting
the error in a block) makes it seem better to leave it. Should throwing
an ERROR! turn out to be actually common, this can be reconsidered
and a refinement named.

The FAIL native takes the place of DO'ing an error to raise it, and
is also able to take a STRING! or a BLOCK!.  The string is sent to
MAKE ERROR! directly, while blocks are processed in a new kind of
"error creation dialect".  The dialect evaluates a WORD! as long as
it does not evaluate to a function, and also will evaluate parens:

     fail ["Problem with foo:" foo "occurred at" (1 + 2)]

...this would behave equivalently to what has been written as:

    do make error! form reduce [
        "problem with foo:" foo "occurred at" (1 + 2)
    ]

Limiting types is to faciliate the dialect becoming more expressive.
It may use SET-WORD!, TAG!, and other choices to cue the fields
and formatting template structure for the error object being returned
to TRAP.  Hence those types are available for future expansion.  In
the meantime, the PAREN!'s general-purpose-escape will allow
for any substitution that FORM REDUCE might otherwise achieve.

It removes a commented out prior placeholder for a FAIL-like native
that was named "CAUSE".  That word may make sense when paired
directly with something like a variable named `error`...but as a
convenience routine that might be used with (for instance) a string it
doesn't communicate that an error has occurred and that execution
will be interrupted.  (RAISE was rejected for similar reasons.)

This is planned as the replacement for DO's handling of errors.  So
calling DO on an ERROR! will now still raise an error, but not the one
you asked for...rather an error directing the user to the use of FAIL.

Similarly, THROW directs users who try and pass errors to use FAIL
(as it would be a common misconception for people from other
languages to think that THROW is what you are supposed to use).
While a refinement was considered to allow throwing errors, the
rarity of the operation and the existence of workarounds (e.g. putting
the error in a block) makes it seem better to leave it.  Should throwing
an ERROR! turn out to be actually common, this can be reconsidered
and a refinement named.
@dram
Copy link

dram commented Sep 11, 2015

Just be curious, I can not figure out what will we lose if functions are evaluated, but SET-WORD!, TAG!, and other types are still treated specially?

@hostilefork
Copy link
Member Author

@dram You lose the ability to know the structure of strings vs. substitutions, because if a function were evaluated it could consume a string.

fail [{segment1} item {segment2}]

If item is a function it can eat segment2, but if it is not then you know segment2 is part of a sequence of display items. Note that errors today are like this:

https://github.com/metaeducation/ren-c/blob/master/src/boot/errors.r

It's a little difficult to plan ahead for a dialect when it doesn't exist yet, so I'm trying to make the most conservative choice. It may be that the constraint gets relaxed.

@hostilefork hostilefork merged commit df1a02a into metaeducation:master Sep 11, 2015
@dram
Copy link

dram commented Sep 11, 2015

Yeah, reasonable.

@hostilefork hostilefork deleted the fail-native branch September 15, 2015 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants