ruby如何区分单引号和双引号字符串?是否涉及C指针?

时间:2016-11-28 08:16:08

标签: ruby string object

有没有人知道ruby解释器如何知道字符串文字(单引号字符串)和双引号字符串之间的区别?

我正在玩字符串,我正在试图弄清楚是否可以将它们从一个更改为另一个。

通过将字符串中的转义序列替换为各自的ascii代码,我能够在某种程度上做到这一点。

\n = 10 -> \\ = 92, n = 110

我拿了这个双引号字符串

"a\e[0;36m X \n"

当解释时会导致

 a X

,X显示青色字体颜色。我将转义序列更改为前面带有反斜杠的字母。这仅在传递的字符串是双字符串时有效。我没有运气传递单引号字符串并将其更改为双引号,所以我可以允许插值。最后我还没有真正改变字符串的内容,所以它的行为就是这样。

现在让我有兴趣弄清楚ruby知道字符串是单引号还是双引号。我确信它有一个执行此操作的机制,因为当我在IRB中玩时,我做到了这一点。

a = "One\nTwo\t Half\n"
=> "One\nTwo\t Half\n"
b = 'Three \n Four \f Five'
=> "Three \\n Four \\f Five"
puts a + b
One
Two  Half
Three \n Four \f Five
=> nil
c = a + b
One
Two  Half
Three \n Four \f Five
=> nil

因此,你可以看到ruby足够聪明,可以记住字符串的某些块是单引号而其他字符串是双引号。我很想知道ruby是否保留了对原始字符串的引用/指针,并且当添加字符串时,它们只是链接在一起,因为它似乎不是在创建一个新的字符串。

我注意到的另一个奇怪的事情是没有办法从方法/函数返回字符串文字。如果有人能指出我的话。让我们留下另一个问题。

更新

我正在玩

ObjectSpace._id2ref(obj.object_id)

所以从上面的例子我尝试了这个。

a.object_id
=> 70219586904340
puts ObjectSpace._id2ref 70219586904340
One
Two  Half
=> nil
b.object_id
=> 70219590675520
puts ObjectSpace._id2ref 70219590675520
Three \n Four \f Five
=> nil
c = a + b
puts ObjectSpace._id2ref c.object_id
One
Two  Half
Three \n Four \f Five
=> nil

我现在正在播放这些对象,但我还没找到它。我想看到里面看到并看到objA + objB或那种程度的东西。

2 个答案:

答案 0 :(得分:3)

没有区别,翻译方面。单引号和双引号字符串仅存在于解析器级别 1 。如果解析器遇到单引号,它会按字面解析字符:

import UIKit

extension UIApplication {

    private struct AssociatedObjectsKeys {
        static var visibleViewControllersPointers = "UIApplication_visibleViewControllersPointers"
    }

    fileprivate var visibleViewControllersPointers: NSPointerArray {
        var pointers = objc_getAssociatedObject(self, &AssociatedObjectsKeys.visibleViewControllersPointers) as! NSPointerArray?
        if (pointers == nil) {
            pointers = NSPointerArray.weakObjects()
            objc_setAssociatedObject(self, &AssociatedObjectsKeys.visibleViewControllersPointers, pointers, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        return pointers!
    }

    var visibleViewControllers: [UIViewController] {
        return visibleViewControllersPointers.allObjects as! [UIViewController]
    }
}

extension UIViewController {

    private static func swizzleFunc(withOriginalSelector originalSelector: Selector, swizzledSelector: Selector) {
        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }

    override open class func initialize() {
        if self != UIViewController.self {
            return
        }
        let swizzlingClosure: () = {
            UIViewController.swizzleFunc(withOriginalSelector: #selector(UIViewController.viewDidAppear(_:)),
                                         swizzledSelector: #selector(uiapplication_visibleviewcontrollers_viewDidAppear(_:)))
            UIViewController.swizzleFunc(withOriginalSelector: #selector(UIViewController.viewDidDisappear(_:)),
                                         swizzledSelector: #selector(uiapplication_visibleviewcontrollers_viewDidDisappear(_:)))
        }()
        swizzlingClosure
    }

    @objc private func uiapplication_visibleviewcontrollers_viewDidAppear(_ animated: Bool) {
        UIApplication.shared.visibleViewControllersPointers.addPointer(Unmanaged.passUnretained(self).toOpaque())
        uiapplication_visibleviewcontrollers_viewDidAppear(animated)
    }

    @objc private func uiapplication_visibleviewcontrollers_viewDidDisappear(_ animated: Bool) {
        let pointers = UIApplication.shared.visibleViewControllersPointers
        for i in 0..<pointers.count {
            if let pointer = pointers.pointer(at: i) {
                let viewController = Unmanaged<AnyObject>.fromOpaque(pointer).takeUnretainedValue() as? UIViewController
                if viewController.isEqual(self) {
                    pointers.removePointer(at: i)
                    break
                }
            }
        }
        uiapplication_visibleviewcontrollers_viewDidDisappear(animated)
    }
}

如果解析器遇到双引号,它会将几个转义序列转换为它们各自的字符(例如,序列str = 'foo\nbar' #=> "foo\\nbar" str.chars #=> ["f", "o", "o", "\\", "n", "b", "a", "r"] str.codepoints #=> [102, 111, 111, 92, 110, 98, 97, 114] 转换为带有代码点10的ASCII字符,即换行符:

\n

您甚至可以混合使用单引号和双引号:

str = "foo\nbar" #=> "foo\nbar"
str.chars        #=> ["f", "o", "o", "\n", "b", "a", "r"]
str.codepoints   #=> [102, 111, 111,  10,  98,  97,  114]

解析器将其视为单个字符串文字str = 'foo' "\n" 'bar' #=> "foo\nbar"

无论哪种方式,都没有“单引号字符串实例”“双引号字符串实例”,只是字符串实例。

Ruby为您提供了几个文字来创建字符串("foo\nbar"'...'"..."%q{...}<<HEREDOC)。结果对象都是一样的。

1 内部有静态字符串?...和内插字符串NODE_STR,但您无法从Ruby中访问该级别。一旦你有一个字符串实例,它只是一堆字符。

答案 1 :(得分:-1)

  

我注意到的另一个奇怪的事情是没有办法回归   方法/函数中的字符串文字。如果有人可以指出   我这个。

// create an extra class for the form to keep your controller clean
class UploadForm extends Form
{
    public function __construct($controller, $name, $action)
    {
        $fields = FieldList::create(
            TextField::create('Name', 'Name'),
            UploadField::create('Upload', 'Upload')
        );

        $actions = FieldList::create(
            FormAction::create($action, 'Submit')
                ->setAttribute('class', 'btn btn-success')
        );

        $validator = RequiredFields::create('Name');

        parent::__construct($controller, $name, $fields, $actions, $validator);
    }
}