In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "what are the characteristics of eval and alias". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "what are the characteristics of eval and alias".
Talk about Eval features derived from Lisp's Evaluation
In some languages, the eval method is a method that executes a string as an expression and returns a result; in others, eval does not necessarily pass in a string, it may also be an abstract syntactic form, Lisp is this language, and Lisp is the first language to use the eval method, and put forward the feature of Evaluation. This also enables the language Lisp to achieve the result of dynamic execution without compiling the system.
The eval method in Lisp expects to pass the expression as an argument to the eval method, declare the return value in a given form, and dynamically evaluate it at run time.
Here is an example of Lisp Evaluation code (Scheme [1] dialect RRS and later):
; set F1 to the expression (+ 1 2 3)
(define F1'(+ 1 2 3))
Execute the expression F1 (+ 1 2 3) and return 6
(eval F1 user-initial-environment)
You may think: this is just a simple feature, why is it called the Dark Arts feature?
Because the eval feature of Evaluation is the basis of many ideas and landing tools. Why? here are a few common scenarios.
The core idea of REPL
If you are iOSer, you will remember that when Swift was born, one of the main functions was the REPL interactive development environment.
Of course, Lisp and Ruby, which are very dynamic, also have corresponding REPL tools. For example, Ruby's irb and pry are both very powerful REPL. Why is REPL mentioned here? Because in this name, E means eval.
The English equivalent of REPL is Read-Eval-Print Loop.
Read reads an expression from the user and puts it into memory; the Eval evaluation function, which is responsible for processing the internal data structure and evaluating the context logic; and the Print output method, which presents the results to the user to complete the interaction.
REPL's model allows people to speed up language learning and debugging, because the "Read-Eval-Print" cycle is more agile than the "Code-Compile-Run-Debug" cycle.
In Lisp's mind, in order to implement a Lisp REPL, you only need to implement these three functions and a round robin function. Of course, we ignore the complex evaluation function here, because it is an interpreter.
With this idea in mind, the simplest REPL can be expressed in the following form:
# in Lisp
(loop (print (eval (read)
# in Ruby
While [case]
Print (eval (read))
End
Have a brief talk about HotPatch
About 2 years ago, iOS was more popular to use JSPatch/RN based on the iOS hotfix and dynamic solution provided by JavaScriptCore. Its core idea is basically to issue JavaScript scripts to call Objective-C, so as to achieve logic injection.
JSPatch is especially known for writing a lot of JavaScript code to call Objective-C methods. Of course, officials also see this efficiency depression, and make JSPatch syntax converters to indirectly optimize this process.
But no matter how optimized, the biggest fundamental problem is that the language Objective-C does not have the eval feature of Evaluation. If you have this feature, you can actually overcome many problems of using JavaScript for bridging.
We all know that Objective-C 's Runtime can dynamically execute any Objective-C method using message forwarding, which gives us an inspiration. If we make a lightweight interpreter, interpret the Objective-C code dynamically, and dynamically execute the Objective-C method using Runtime message forwarding, we can implement a "quasi-eval method".
This idea has been opened up by some friends on GitHub, Demo-OCEval [2]. Unlike the compilation process of Clang, he streamlined:
The precompilation of Preprocesser is removed, Lexer lexical analysis and Parser syntax analysis are retained, NSMethodSignature encapsulation method is used, combined with recursive descent, and Runtime is used to forward messages.
There is another OCRunner [3] project that uses this line of thinking.
All these are realized by self-made interpreter, eval features, and then with libffi.
Eval and binding in Ruby
The eval method in Ruby is actually easy to understand, which is to pass in the Ruby code as a string as an argument and execute it.
Str = 'Hello'
Puts eval ("str + 'CocoaPods'") # Hello CocoaPods
As an example above, we find that the incoming code str + 'CocoaPods' has become Ruby code execution in the eval method and returns the result' Hello CocoaPods' string.
As mentioned in the parsing Logic of Podfile, the eval method is also used in CocoaPods to execute the logic in the Podfile file in the form of a Ruby script.
Def self.from_ruby (path, contents = nil)
#...
Podfile = Podfile.new (path) do
Begin
# execute the logic in Podfile
Eval (contents, nil, path.to_s)
Rescue Exception = > e
Message = "Invalid `# {path.basename}` file: # {e.message}"
Raise DSLError.new (message, path, e, contents)
End
End
Podfile
End
Of course, only the first layer of the eval method is used in CocoaPods, which is definitely not enough for us learners.
In Ruby, Kernel has a method binding, which returns an object of type Binding. This Binding object is commonly known as binding, which encapsulates all the bindings of the current execution context, including variables, methods, Block and self name bindings, which directly determine the execution environment in the object-oriented language.
So how do you use this Binding object in the eval method? It is actually the second parameter of the eval method. This is not used in running Podfile code in CocoaPods. Let's do an example:
Def foo
Name = 'Gua'
Binding
End
Eval ('p name', foo) # Gua
In this example, our foo method is the execution environment we mentioned above, where the variable name is defined and the result of the binding method call is returned at the end of the method body. When you use the eval method below, you can successfully output the name variable by passing it as the Kernel#binding input parameter.
TOPLEVEL_BINDING global constant
The main object is the top-level scope in Ruby, and any object in Ruby needs to be instantiated at least in the secondary scope. To access the context of a main object anytime, anywhere, Ruby provides a global constant called TOPLEVEL_BINDING, which points to an object that encapsulates the top-level binding. Easy to understand, for example:
@ a = "Hello"
Class Addition
Def add
TOPLEVEL_BINDING.eval ("@ a + = 'Gua'")
End
End
Addition.new.add
P TOPLEVEL_BINDING.receiver # main
P @ a # Hello Gua
In this code, the Binding#receiver method returns the recipient of the Kernel#binding message. To do this, the call execution context is saved-in our case, the main object.
Then we use the TOPLEVEL_BINDING global constant in an instance of the Addition class to access the global @ a variable.
On the characteristics of Ruby Eval
The above brief introduction if you have read the fourth chapter of the divine book SICP (Structture and Interpretation of Computer Programs), you will have a deeper understanding.
We treat all statements as evaluations and describe the process in language. The evaluators written in the same language as the evaluated language are called meta-loops; eval in meta-loops, the parameters are an expression and an environment, which is also completely consistent with Ruby's eval method.
I have to say that many of Ruby's ideas stand on the shoulders of SICP.
Alias similar to Method Swizzling
For the vast majority of iOSer must be very familiar with the so-called Runtime dark magic of Method Swizzling. This is actually a feature that most dynamic languages have.
In iOS, the substitution of methods is achieved by using the point exchange between Selector and Implementation (that is, IMP). This replacement occurs at run time.
There is a similar approach in Ruby. In order to fully understand the "Method Swizzling" in Ruby, we need to understand these concepts about metaprogramming ideas: Open Class features and surround aliases. These two features are also the core dependencies for CocoaPods plug-in.
Open Class and specific methods
The Open Class feature is to add methods to a class again after it has been defined. The implementation in Ruby is to define a class with the same name.
In Ruby, it is not considered a compilation error like Objective-C and Swift, which needs to use the special keyword syntax of Category and Extension to agree on extension. Instead, all the definition methods in the class with the same name are appended to the defined old class, the increase of the same name and the overwrite of the same name. The following is the sample code:
Class Foo
Def m1
Puts "M1"
End
End
Class Foo
Def m2
Puts "m2"
End
End
Foo.new.m1 # m1
Foo.new.m2 # m2
Class Foo
Def m1
Puts "M1 new"
End
End
Foo.new.m1 # m1 new
Foo.new.m2 # m2
Specific methods are somewhat similar to Open Class, except that additional methods are not attached to the class, but to specific instances. Attaching to a method exists only in the target instance and does not affect the class to other instances. Sample code:
Class Foo
Def m1
Puts "M1"
End
End
Foo1 = Foo.new
Def foo1.m2 ()
Puts "m2"
End
Foo1.m1 # m1
Foo1.m2 # m2
Foo2 = Foo.new
Foo2.m1 # m1
# foo2.m2 undefined method `m2' for # (NoMethodError)
Surround aliases (Around Aliases)
In fact, wrapping aliases is just a special way of writing, using Ruby's alias keyword and the Open Class features mentioned above.
First of all, let's introduce the alias keyword of Ruby, which is actually very simple, which is to give a method an alias. But with the previous Open Class features, alias can achieve what we call the Method Swizzling effect.
Class Foo
Def m1
Puts "M1"
End
End
Foo = Foo.new
Foo.m1 # m1
Class Foo
Alias: origin_m1: m1
Def m1
Origin_m1
Puts "Hook it!"
End
End
Foo.m1
# m1
# Hook it!
Although the Foo#m1 method has been defined in the first location, due to the rewriting mechanism of Open Class and the alias setting of alias, we have modified M1 to a new method, and the old M1 method can also be called using origin_m1. This completes the Method Swizzling mechanism similar to that in Objective-C.
To summarize the surround alias is to define an alias for the method, and then redefine the method to call the old method with the alias in the new method.
Monkey Patch (Monkey Patch)
Now that we're talking about alias aliases, by the way, monkey patches are a feature. The monkey patch is different from the way it surrounds aliases. Its main purpose is to replace dynamically at run time and to temporarily avoid program crashes.
Let's talk about the background, because of the features of Open Class and surround aliases, it's already easy for Ruby to change its properties at run time. But what if we now have a requirement that * * we need to Patch dynamically * * instead of replacing alias globally?
Here we introduce the other two keywords refine and using in Ruby, through which we can dynamically implement Patch. For example:
Class Foo
Def m1
Puts "M1"
End
End
Foo = Foo.new
Foo.m1 # m1
"
Define a Patch
"
Module TemproaryPatch
Refine Foo do
Def m1
Puts "M1 bugfix"
End
End
End
Using TemproaryPatch
Foo2 = Foo.new
Foo2.m1 # m1 bugfix
In the above code, we first use the refine method to redefine the M1 method, which does not take effect immediately after it is defined, but only when we use using TemporaryPatch. In this way, the requirements of dynamic Patch are realized.
Thank you for your reading, the above is the content of "what are the characteristics of eval and alias". After the study of this article, I believe you have a deeper understanding of what the characteristics of eval and alias are, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.