আপনি কীভাবে এলিক্সির মধ্যে চলক প্রকারের জন্য পরীক্ষা করেন


138

এলিক্সির মধ্যে আপনি পাইথনের মতো প্রকারের জন্য কীভাবে পরীক্ষা করেন:

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

আমি এলিক্সিতে পড়েছি যেমন 'is_bitstring', 'is_float', 'is_list', 'is_map' ইত্যাদির মতো টাইপ চেকার রয়েছে, তবে টাইপটি কী হতে পারে তা আপনার যদি ধারণা না থাকে তবে কী হবে?

উত্তর:


104

এলিক্সির / এরলংয়ে কোনও ভেরিয়েবলের ধরণ পাওয়ার সরাসরি কোনও উপায় নেই।

সেই অনুযায়ী কাজ করতে আপনি সাধারণত কোনও পরিবর্তনশীলের ধরণ জানতে চান; is_*ভেরিয়েবলের ধরণের ভিত্তিতে কাজ করতে আপনি ক্রিয়াগুলি ব্যবহার করতে পারেন ।

আপনি শিখুন কিছু এর্লং এরলং (এবং এভাবে এলিক্সির মধ্যে) টাইপ করার একটি দুর্দান্ত অধ্যায় রয়েছে

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
এরল্যাং / এলিক্সিরের আসলে কোনও ধরণের তথ্য নেই? ভাষা ব্যবহারের যোগ্য হওয়ার জন্য আমার কি বিদ্যমান ধরণের উপরে একটি নতুন নতুন মোড়ক তৈরি করার দরকার আছে? ওও
দিমিত্রি

2
@ দিমিত্রি আপনাকে ব্যবহারের যোগ্য বলতে কী বোঝায়? আমি কি এমন একটি দৃ of় উদাহরণ দেখতে পাচ্ছি যেখানে আপনি এমন কিছুর ফলাফল ব্যবহার করবেন typeof(variable)?
কি আপনি

1
যখন কোনও প্রোগ্রাম সংকলন করার সময় ছেড়ে যায় এবং রানটাইমে প্রবেশ করে, কোনও বস্তুটি কী কী তা হারিয়ে যায় তার সমস্ত তথ্য। যখন আমি কোনও চলমান প্রোগ্রামের তথ্য পরিদর্শন করতে চাই, তখন কী চলছে তা জানার একমাত্র উপায় হ'ল মানচিত্রের নেটওয়ার্কের মাধ্যমে প্রকাশিত বিষয়গুলি পরীক্ষা করে। যদি টাইপ তথ্য উপলব্ধ না হয় এবং আমি টাইপটি পরিদর্শন করতে চাই, তবে টাইপটি ইতিমধ্যে প্রকাশিত হয়েছে কিনা তার চেয়ে তার 'প্রকারটি অর্জন করতে বস্তুর বিশ্লেষণ করতে আরও অনেক বেশি ব্যয় হবে। টাইপফ আমাদের চলমান সিস্টেম বিশ্লেষণ করতে এবং রানটাইম এ এটি এমনভাবে প্রসারিত করতে দেয় যা টাইপচেকিং এবং পলিমারফিজমকে অনুমতি দেয়।
দিমিত্রি

2
আরো নির্দিষ্ট করা; টাইপফোর সবচেয়ে দরকারী ব্যবহার হ'ল [টাইপ স্ট্রিং, ফাংশন] এর একটি হ্যাশ টেবিলটি অজানা তালিকায় সরাসরি ম্যাপ করার ক্ষমতা। উদাহরণ স্বরূপ; আইও.পুটস foo = [1, "hello", [1, 2, 3]]কোড সহ ম্যাপ করা যায় না , Enum.map(foo, fn(x) -> IO.puts x end)কারণ [1,2, 3] অক্ষর হিসাবে পড়বে (কেন এরালং !!?), এবং আপনাকে হাসি মুখের একগুচ্ছ দেখিয়ে দেবে (চেষ্টা করে দেখুন!) সুতরাং আমরা পরিদর্শন ব্যবহার করতে বাধ্য হই যদিও তদন্তের প্রয়োজন কেবল যদি এটি তালিকা থাকে তবে অন্যথায় বেশিরভাগ সময় আমাদের এটির প্রয়োজন হয় না। typof আমাদের যদি বিবৃতি (O (n)) অভিধান অভিধানে (O (1)) রূপান্তর করতে দেয়।
দিমিত্রি

1
এই ধরণের ব্যবহারের জন্য দিমিত্রি এলিক্সির প্রোটোকল দরকারী হবে। elixir-lang.org/getting-st সূত্র /Printable প্রোটোকলস। html আপনি নিজের প্রোটোকল প্রয়োগ করতে পারেন যা মুদ্রণের আচরণকে আবৃত করে এবং উদাহরণস্বরূপ পূর্ণসংখ্যার তালিকা পরিবর্তন করে। কেবল এটি নিশ্চিত করে নিন যে আপনি এটি এরং কোড দিয়ে ব্যবহার করছেন না — বা আপনি ভাবছেন যে আপনি বার্তাগুলির পরিবর্তে কেন পূর্ণসংখ্যার তালিকা দেখছেন তা ভেবে আপনার মাথা আঁচড়ান।
ম্যাট জ্যাডজাক

168

ইলিক্সার ১.২ থেকে শুরু করে আইএএক্স-তে একটি iকমান্ড রয়েছে যা কোনও এলিক্সির ভেরিয়েবলের ধরণ এবং আরও তালিকাবদ্ধ করবে।

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

আপনি যদি এলিক্সির কোনও ডেটা টাইপের জন্য কোনও ফাংশন বাস্তবায়ন করতে চান তবে তা করার উপায় হ'ল আপনি যে ফাংশনটিতে কাজ করতে চান তার জন্য সমস্ত প্রকার প্রোটোকল এবং প্রোটোকল প্রয়োগ করা। দুর্ভাগ্যক্রমে, আপনি প্রহরীদের মধ্যে একটি প্রোটোকল ফাংশন ব্যবহার করতে পারবেন না। তবে, একটি সাধারণ "টাইপ" প্রোটোকল প্রয়োগ করা খুব সোজা হবে।


1
2019-এ এই ত্রুটিটি ফেরত দেয় undefined function i/1- তথ্য / 1
ক্র্যাভার

1
এটি এখনও এলিক্সির 1.8.1 এ কাজ করে। আপনার অবশ্যই ইলিক্সারের একটি খুব পুরানো সংস্করণ ইনস্টল করা উচিত।
ফ্রেড ম্যাজিক ওয়ান্ডার কুকুর

2
@ ক্রিভার @ ফ্রেড-দ্য ম্যাজিক-আশ্চর্য-কুকুর আপনি উভয়ই সঠিক: :)। &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

আর একটি পদ্ধতি হ'ল প্যাটার্ন ম্যাচিং ব্যবহার করা। বলুন আপনি টাইমেক্স ব্যবহার করছেন যা একটি %DateTime{}স্ট্রাক্ট ব্যবহার করে এবং আপনি দেখতে চান যে কোনও উপাদান একটি কিনা। পদ্ধতিতে প্যাটার্ন ম্যাচ ব্যবহার করে আপনি একটি মিল খুঁজে পাবেন।

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

def is_a_datetime?(_) do
  false
end

1
বা, যেমন গৃহীত উত্তরটি মন্তব্য করেছে তবে তা জোর দেয়নি: usually আপনি সাধারণত সেই অনুযায়ী কাজ করার জন্য কোনও পরিবর্তনশীলের ধরণটি জানতে চান « এলিক্সিতে আপনি সেই অনুযায়ী প্যাটার্ন ম্যাচিংয়ের দ্বারা কাজ করেন, 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 / দার্শনিক-প্রস্তর । ফেনেটিক এখনও প্রথম দিনগুলিতে রয়েছে তবে এটি এটি এবং আরও অনেক কিছু করতে পারে।
ফ্রেড ম্যাজিক ওয়ান্ডার কুকুর

নিজেকে সহজেই একটি বাহ্যিক নির্ভরতার সাথে আবদ্ধ করুন? কীভাবে এটি আমার বন্ধুদের সাথে কোড ভাগ করে নেওয়ার ক্ষমতা বাড়ায়? এটি 2 সমস্যার একটি রাস্তা।
দিমিত্রি

@Ks সম্পাদনা করার জন্য ধন্যবাদ; আমি এখন ঠিক 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
প্রশ্নের উত্তর নয়, এমনকি কাছেও নয়
লোফিল্ড থিওরি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.