आप अमृत के चर के प्रकार की जांच कैसे करते हैं


138

अमृत ​​में आप इस तरह के अजगर के रूप में कैसे की जाँच करें:

>>> a = "test"
>>> type(a)
<type 'str'>
>>> b =10
>>> type(b)
<type 'int'>

मैंने अमृत में पढ़ा है कि 'is_bitstring', 'is_float', 'is_list', 'is_map' इत्यादि जैसे टाइप चेकर हैं, लेकिन अगर आपको अंदाजा नहीं है कि टाइप क्या हो सकता है?

जवाबों:


104

Elixir / Erlang में एक चर का प्रकार प्राप्त करने का कोई सीधा तरीका नहीं है।

आप आमतौर पर एक चर का प्रकार जानना चाहते हैं ताकि उसके अनुसार कार्य किया जा सके; आप is_*चर के प्रकार के आधार पर कार्य करने के लिए कार्यों का उपयोग कर सकते हैं ।

आप कुछ सीखें Erlang में Erlang (और इस प्रकार Elixir) में टाइप करने के बारे में एक अच्छा अध्याय है

is_*कार्यों के परिवार का उपयोग करने का सबसे मुहावरेदार तरीका संभवतः पैटर्न मैचों में उनका उपयोग करना होगा:

def my_fun(arg) when is_map(arg), do: ...
def my_fun(arg) when is_list(arg), do: ...
def my_fun(arg) when is_integer(arg), do: ...
# ...and so on

3
क्या Erlang / Elixir के पास वास्तव में कोई संग्रहीत प्रकार की जानकारी नहीं है? क्या मुझे वास्तव में प्रयोग करने योग्य भाषा के लिए मौजूदा प्रकारों पर एक नया आवरण बनाने की आवश्यकता है? ऊ
दिमित्री 3

2
@ हम आपको प्रयोग करने योग्य से क्या मतलब है? क्या मैं एक ठोस उदाहरण देख सकता हूँ जहाँ आप किसी चीज़ के परिणाम का उपयोग करेंगे typeof(variable)?
whatyouhide

1
जब कोई प्रोग्राम समय संकलित करता है और रनटाइम में प्रवेश करता है, तो किसी वस्तु के खो जाने के बारे में सभी जानकारी। जब मैं एक चल रहे कार्यक्रम की जानकारी का निरीक्षण करना चाहता हूं, तो यह जानने का एकमात्र तरीका है कि क्या चल रहा है, चीजों का निरीक्षण करके जो कि नक्शे के एक नेटवर्क के माध्यम से उजागर होते हैं। यदि प्रकार की जानकारी उपलब्ध नहीं है, और मैं प्रकार का निरीक्षण करना चाहता हूं, तो इसके प्रकार को प्राप्त करने के लिए ऑब्जेक्ट का विश्लेषण करने के लिए लागत का अधिक से अधिक खर्च होता है यदि प्रकार पहले से ही उजागर हो गया था। टाइपोफ हमें रनिंग सिस्टम का विश्लेषण करने और इसे रनटाइम पर इस तरह से विस्तारित करने की अनुमति देता है जिससे टाइपकास्टिंग और बहुरूपता की अनुमति मिलती है।
दिमित्री

2
अधिक विशिष्ट होना; टाइपोफ़ का सबसे उपयोगी उपयोग अज्ञात की सूची पर सीधे [टाइप स्ट्रिंग, फ़ंक्शन] की एक हैश तालिका को मैप करने की क्षमता है। उदाहरण के लिए; IO.puts को foo = [1, "hello", [1, 2, 3]]कोड के साथ मैप नहीं किया जा सकता है Enum.map(foo, fn(x) -> IO.puts x end)क्योंकि [1,2, 3] को अक्षर के रूप में पढ़ा जाएगा (Whylang !!)? इसलिए हमें निरीक्षण का उपयोग करने के लिए मजबूर किया जाता है भले ही निरीक्षण केवल तभी आवश्यक हो जब यह एक सूची हो, अन्यथा अधिकांश समय हमें इसकी आवश्यकता नहीं होती है। टाइपो हमें बयानों (O (n)) को डिक्शनरी लुकअप (O (1)) में बदल देता है।
दिमित्री

1
@ उस प्रकार के उपयोग के लिए अमृत प्रोटोकॉल उपयोगी होगा। elixir-lang.org/getting-started/protocols.html आप अपने स्वयं के Printableप्रोटोकॉल को लागू कर सकते हैं जो रैपर्स और प्रिंटिंग के व्यवहार को बदल देता है जैसे पूर्णांकों की सूची। बस यह सुनिश्चित करें कि आप इसका उपयोग एर्लांग कोड के साथ नहीं करते हैं - या आप अपने सिर को खरोंचते हुए सोचेंगे कि संदेशों के बजाय आप पूर्णांकों की सूची क्यों देख रहे हैं।
मैट जडकैक

168

अमृत ​​1.2 में शुरू होने iका मतलब है कि iex में एक कमांड है जो किसी भी अमृत चर के प्रकार और अधिक को सूचीबद्ध करेगा।

iex> foo = "a string" 
iex> i foo 
Term
 "a string"
Data type
 BitString
Byte size
 8
Description
 This is a string: a UTF-8 encoded binary. It's printed surrounded by
 "double quotes" because all UTF-8 encoded codepoints in it are        printable.
Raw representation
  <<97, 32, 115, 116, 114, 105, 110, 103>>
Reference modules
  String, :binary

यदि आप iकमांड के कोड में देखते हैं तो आप देखेंगे कि यह एक प्रोटोकॉल के माध्यम से लागू किया गया है।

https://github.com/elixir-lang/elixir/blob/master/lib/iex/lib/iex/info.ex

यदि आप Elixir में किसी भी डेटा प्रकार के लिए कोई फ़ंक्शन लागू करना चाहते हैं, तो ऐसा करने का तरीका प्रोटोकॉल को परिभाषित करना है और उन सभी डेटा प्रकारों के लिए प्रोटोकॉल को लागू करना है, जिन्हें आप कार्य करना चाहते हैं। दुर्भाग्य से, आप गार्ड में प्रोटोकॉल फ़ंक्शन का उपयोग नहीं कर सकते। हालांकि, एक सरल "प्रकार" प्रोटोकॉल लागू करने के लिए बहुत सरल होगा।


1
2019 में यह एक त्रुटि undefined function i/1- जानकारी के लिए वही / 1
krivar

1
यह अभी भी एलिक्सिर 1.8.1 में काम करता है। आपके पास बहुत पुराना संस्करण स्थापित होना चाहिए।
फ्रेड द मैजिक वंडर डॉग

2
@krivar @ fred-the-Magic-Wonder-dog तुम दोनों सही हो :)। &i/1पर एक समारोह है IEx.Helpers। यदि आप इसे &IEx.Helpers.i/1अपने वेनिला अमृत में डालते हैं , तो आप CompileErrorतब तक उत्पन्न करेंगे जब तक कि आप अपने :iexआवेदन में इसे शामिल नहीं करते mix.exs
popedotninja

39

डिबगिंग के उद्देश्यों के लिए, यदि आप iex में नहीं हैं, तो आप इसे सीधे कॉल कर सकते हैं:

IEx.Info.info(5)
=> ["Data type": "Integer", "Reference modules": "Integer"]

1
यदि आप इसे अपने लॉग इन IO.inspect (IEx.Info.info (5))
Guillaume

24

एक अन्य दृष्टिकोण पैटर्न मिलान का उपयोग करना है। कहते हैं कि आप Timex का उपयोग कर रहे हैं, जो एक %DateTime{}संरचना का उपयोग करता है , और आप यह देखना चाहते हैं कि क्या तत्व एक है। आप विधि में पैटर्न मिलान का उपयोग करके एक मैच पा सकते हैं।

def is_a_datetime?(%DateTime{}) do
  true
end

def is_a_datetime?(_) do
  false
end

1
या, जैसा कि स्वीकृत उत्तर में टिप्पणी की गई थी, लेकिन तनाव नहीं था: »आप आमतौर पर एक चर का प्रकार जानना चाहते हैं ताकि उसके अनुसार कार्य किया जा सके«। Elixir में आप पैटर्न मिलान के अनुसार कार्य करते हैं, न कि switch/ के द्वारा case
मारीतोमो

18

मैं बस किसी को उम्मीद है कि वास्तव में एक समझदार संस्करण के लिए यहाँ छोड़ दूँगा। फिलहाल इस पर कोई अच्छा जवाब नहीं आ रहा है ...

defmodule Util do
    def typeof(self) do
        cond do
            is_float(self)    -> "float"
            is_number(self)   -> "number"
            is_atom(self)     -> "atom"
            is_boolean(self)  -> "boolean"
            is_binary(self)   -> "binary"
            is_function(self) -> "function"
            is_list(self)     -> "list"
            is_tuple(self)    -> "tuple"
            true              -> "idunno"
        end    
    end
end

पूर्णता की खातिर, मामलों की जांच करें:

cases = [
    1.337, 
    1337, 
    :'1337', 
    true, 
    <<1, 3, 3, 7>>, 
    (fn(x) -> x end), 
    {1, 3, 3, 7}
]

Enum.each cases, fn(case) -> 
    IO.puts (inspect case) <> " is a " <> (Util.typeof case)
end

यहाँ प्रोटोकॉल के साथ एक समाधान है; मुझे यकीन नहीं है कि अगर वे तेज हैं (मुझे यकीन है कि वे सभी प्रकारों पर एक लूप नहीं कर रहे हैं), लेकिन यह बहुत बदसूरत है (और नाजुक; यदि वे एक मूल प्रकार या नाम जोड़ते हैं या हटाते हैं, तो यह इसे तोड़ देगा)।

defprotocol Typeable, do: def typeof(self)
defimpl Typeable, for: Atom, do: def typeof(_), do: "Atom"
defimpl Typeable, for: BitString, do: def typeof(_), do: "BitString"
defimpl Typeable, for: Float, do: def typeof(_), do: "Float"
defimpl Typeable, for: Function, do: def typeof(_), do: "Function"
defimpl Typeable, for: Integer, do: def typeof(_), do: "Integer"
defimpl Typeable, for: List, do: def typeof(_), do: "List"
defimpl Typeable, for: Map, do: def typeof(_), do: "Map"
defimpl Typeable, for: PID, do: def typeof(_), do: "PID"
defimpl Typeable, for: Port, do: def typeof(_), do: "Port"
defimpl Typeable, for: Reference, do: def typeof(_), do: "Reference"
defimpl Typeable, for: Tuple, do: def typeof(_), do: "Tuple"

IO.puts Typeable.typeof "Hi"
IO.puts Typeable.typeof :ok

यदि आप वास्तव में "टाइप" चेकर चाहते हैं, तो आप आसानी से दार्शनिक के स्टोन ऑर्ग में टूल का उपयोग करके निर्माण कर सकते हैं। github.com/philosophers-stone । फेनमैटिक अभी भी शुरुआती दिनों में है, लेकिन यह यह और बहुत कुछ कर सकता है।
फ्रेड द मैजिक वंडर डॉग

आसानी से अपने आप को एक बाहरी निर्भरता से बांधें? यह कैसे दोस्तों के साथ कोड साझा करने की मेरी क्षमता में सुधार करने जा रहा है? यह 2 समस्याओं का मार्ग है।
दिमित्री

@Aks के संपादन के लिए धन्यवाद; मैं वास्तव में 4 स्थानों पर वापस जा सकता हूं ^ _ ^
दिमित्री

15

मैं सिर्फ https://elixirforum.com/t/just-created-a-typeof-module/2583/5 :) से कोड पेस्ट करता हूं

defmodule Util do
  types = ~w[function nil integer binary bitstring list map float atom tuple pid port reference]
  for type <- types do
    def typeof(x) when unquote(:"is_#{type}")(x), do: unquote(type)
  end
end

चतुर बोली का उपयोग! जितना अधिक मैं अमृत कोड देखता हूं उतना ही यह मुझे पर्ल की याद दिलाता है; कि ~ w निर्माण qw // के समान दिखता है। मुझे आश्चर्य है कि अगर पर्ल के पास लिस्प्लाइक उद्धरण का अनुकरण करने के लिए कुछ चतुर तंत्र है।
दिमित्री

मुझे आश्चर्य है कि बोली कैसे काम करती है; क्या यह एक नियमित अभिव्यक्ति प्रीप्रोसेसर का उपयोग करके अनुकरण किया जा सकता है, या क्या इसे मैक्रो विस्तार करने के लिए पूरे कोड के माध्यम से पार्सर चलने की आवश्यकता होती है।
दिमित्री

1

मैं एक ऐसी स्थिति में आया था जब पैरामीटर को जांचने की जरूरत है कि कुछ प्रकार के होने की आवश्यकता है। शायद बेहतर तरीके से सक्रिय हो सकता है।

ऐशे ही:

@required [{"body", "binary"},{"fee", "integer"}, ...]
defp match_desire?({value, type}) do
  apply(Kernel, :"is_#{type}", [value])
end

उपयोग:

Enum.map(@required, &(match_desire?/1))

1

सिर्फ इसलिए कि किसी ने इसका उल्लेख नहीं किया है

IO.inspect/1

ऑब्जेक्ट कंसोल करने के लिए आउटपुट ... इसका लगभग JSON.stringify के बराबर है

बहुत उपयोगी है जब आप सिर्फ अपने जीवन के लिए यह पता नहीं लगा सकते हैं कि एक परीक्षण में कोई वस्तु कैसी दिखती है।


4
सवाल का जवाब नहीं, करीब भी नहीं
LowFieldTheory
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.