Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the characteristics of eval and alias

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report