Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Scoping in try/catch/after
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  2 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Jake Mitchell  
View profile  
 More options Apr 12 2012, 1:37 am
From: Jake Mitchell <jacob.d.mitch...@gmail.com>
Date: Wed, 11 Apr 2012 22:37:22 -0700 (PDT)
Local: Thurs, Apr 12 2012 1:37 am
Subject: Scoping in try/catch/after

I've started a loose port of Ruby Koans<https://github.com/edgecase/ruby_koans>to better understand the nuances of Elixir and share what I learn.  While
writing tests for try/catch/after I realized I couldn't update variables
defined outside the try, catch, or after clauses.

  test :affect_state_from_try_catch_after do
    defrecord StateTracker, from_try: :default, from_catch: :default,
from_after: :default
    outside_state = StateTracker.new

    try do
      assert_equal :default, outside_state.from_try  # passes
      outside_state = outside_state.from_try(:new_value)
      assert_equal :new_value, outside_state.from_try  # passes
      throw :something
    catch: caught_value
      assert_equal :default, outside_state.from_catch  # passes
      outside_state = outside_state.from_catch(:new_value)
      assert_equal :new_value, outside_state.from_catch  # passes
    after:
      assert_equal :default, outside_state.from_after  # passes
      outside_state = outside_state.from_after(:new_value)
      assert_equal :new_value, outside_state.from_after  # passes
    end

    assert_equal :new_value, outside_state.from_try  # fails: nil
    assert_equal :new_value, outside_state.from_catch  # fails: nil
    assert_equal :new_value, outside_state.from_after  # fails: nil
  end

Documentation for the try defmacro says variables created inside the try
clause can't be accessed externally.  What it doesn't address is reading or
updating preexisting variables.  Based on the test above, reading from a
preexisting variable is no problem, but updates don't take hold outside of
the try/catch/after.

We can still affect the state of the outer scope using the result of the
try statement, but it requires writing try statements like what's shown
below.

  def some_function()  
    try_result = try do
                   do_something()
                 catch: caught_value
                   log_catch(caught_value)
                   {:thrown, caught_value}
                 after:
                   IO.puts "finished try/catch"
                 end
    process_result(try_result)
  end

I bring it up because many other languages permit changing the state
surrounding the try statement from within all parts of the try statement.  
For example, here's a Ruby method that's similar to the Elixir test, except
it behaves much differently:

def affect_state_from_begin_rescue_ensure_test
  outside_state = {
    :from_begin => nil,
    :from_rescue => nil,
    :from_ensure => nil
  }

  begin
    outside_state[:from_begin] = :new_value
    raise
  rescue
    outside_state[:from_rescue] = :new_value  
  ensure
    outside_state[:from_ensure] = :new_value
  end

  puts "From begin: #{outside_state[:from_begin]}"  # :new_value
  puts "From rescue: #{outside_state[:from_rescue]}"  # :new_value
  puts "From ensure: #{outside_state[:from_ensure]}"  # :new_value
end

Not being able to affect surrounding state from the after clause is
particularly strange to me.  Unlike the try and catch clauses, the after
clause has no impact on the result of the overall try statement.  
Additionally, we can't write to variables in the surrounding scope that
could impact the return value of the enclosing function.  From what I've
seen in examples and the Elixir codebase, the after clause has only been
used to make system calls, such as interacting with the file system or
writing to standard output  Many other languages let the "finally" clause
affect outer state and thereby affect the enclosing function's return
value.  Do we want that possibility in Elixir too?

It's not my intention to cause commotion over this.  Don't hesitate to
bring factors I haven't addressed or share your own take on the matter.  I
could easily be missing something, like relevant details about
Erlang--definitely a newb here :)

Thanks!

-Jake


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
José Valim  
View profile  
 More options Apr 12 2012, 5:46 am
From: José Valim <jose.va...@gmail.com>
Date: Thu, 12 Apr 2012 06:46:21 -0300
Local: Thurs, Apr 12 2012 5:46 am
Subject: Re: Scoping in try/catch/after
Hello Jake,

Thanks for the feedback and trying out Elixir. Unfortunately the current limitation is intrinsic to the Erlang VM, so there isn't anything we can do. If you want to update the docs to make your case more clear, a pull request is very welcome.

Thanks,


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »