Случается, когда вы пытаетесь вызвать функцию, которая еще не определена. Общие причины включают отсутствующие расширения и включают в себя объявление условной функции, функцию в объявлении функции или простые опечатки.
Пример 1 - Декларация условной функции
$someCondition = false;
if ($someCondition === true) {
function fn() {
return 1;
}
}
echo fn(); // triggers error
В этом случае fn()
никогда не будет объявлено, потому что $someCondition
не соответствует действительности.
Пример 2 - Функция в объявлении функции
function createFn()
{
function fn() {
return 1;
}
}
echo fn(); // triggers error
В этом случае fn
будет объявлен только после вызова createFn()
. Обратите внимание, что последующие вызовы createFn()
вызовут ошибку об обновлении существующей функции.
Вы также можете увидеть это для встроенной функции PHP. Попробуйте найти функцию в официальном руководстве и проверьте, к какому «расширению» (к нему принадлежит PHP-модуль), и какие версии PHP поддерживают его.
В случае отсутствующее расширение, установите это расширение и включите его в php.ini. Обратитесь к Инструкции по установке в Руководстве по PHP для расширения вашей функции. Возможно, вы также сможете включить или установить расширение с помощью диспетчера пакетов (например, apt
в Debian или Ubuntu, yum
в Red Hat или CentOS ) или панель управления в среде общедоступного хостинга.
Если функция была введена в более новой версии PHP из того, что вы используете, вы можете найти ссылки на альтернативные реализации в руководстве или в разделе комментариев , Если он был удален из PHP, найдите информацию о том, почему, поскольку это может быть уже не нужно.
В случае отсутствия включено, обязательно включите файл, объявляющий функцию перед вызовом функции.
В случае опечаток исправить опечатку.
Вопросы, относящиеся
От статьи:
$
и @
не указывают на переменный тип данных как в Perl, а скорее функционируют как операторы разрешения области видимости. 99.0
) или явным преобразованием (99.to_f
). Это недостаточно для добавления точки (99.
), потому что числа восприимчивы к синтаксису метода. 0
, ""
и []
все оценены к [1 112]. В C выражение 0 ? 1 : 0
оценивает к [1 114] (т.е. ложь). В Ruby, однако, это уступает 1
, поскольку все числа оценивают к [1 116]; [только 1 117] и false
оценивают к [1 119]. Заключение к этому правилу - то, что методы Ruby условно —, например, регулярное выражение ищет — числа возврата, строки, списки или другие неложные значения на успехе, но nil
при отказе (например, несоответствие). Это соглашение также используется в Smalltalk, где только специальные объекты true
и false
могут использоваться в булевом выражении. char
для символов). Это может вызвать неожиданности при разрезании строк: "abc"[0]
урожаи 97
(целое число, представляя код ASCII первого символа в строке); получить "a"
использование "abc"[0,1]
(подстрока длины 1) или "abc"[0].chr
. нотация statement until expression
, в отличие от эквивалентных операторов других языков (например, do { statement } while (not(expression));
в C/C ++/...), на самом деле никогда не выполняет оператор, если выражение уже true
. Это вызвано тем, что statement until expression
на самом деле синтаксический сахар [более чем 1 163]
until expression
statement
end
, эквивалент которого в C/C++ while (not(expression)) statement;
точно так же, как statement if expression
, эквивалент [1 164]
if expression
statement
end
Однако, нотация
begin
statement
end until expression
в Ruby на самом деле выполнит оператор однажды, даже если выражение будет уже верно.
Greeting << " world!" if Greeting == "Hello"
не генерирует ошибку или предупреждение. Это подобно [1 136] переменные в Java, но Ruby действительно также имеет функциональность, чтобы "заморозить" объект, в отличие от Java. функции Some, которые отличаются особенно от других языков:
обычные операторы для условных выражений, and
и or
, не следуют нормальным правилам приоритета: and
не связывает более трудный, чем [1 140]. Ruby также имеет операторы ||
и &&
выражения, которые работают как ожидалось.
def
внутренний def
не делает то, что мог бы ожидать Python программист:
def a_method
x = 7
def print_x; puts x end
print_x
end
Это дает ошибку [приблизительно 1 145] не быть определенным. Необходимо использовать Proc
.
функции Language
()
, избегать неоднозначного значения кода. Не использование ()
является все еще обычной практикой и может быть особенно хорошо использовать Ruby в качестве самого человекочитаемого проблемно-ориентированного языка программирования, наряду с методом, названным method_missing()
. Связанный с ответом monkut, Ruby to_foo
методы намекают, как строгий преобразование они сделают.
Короткие как to_i
, to_s
говорят этому быть ленивым, и преобразовать их в целевой тип, даже если они не в состоянии быть представленными точно в том формате. Например:
"10".to_i == 10
:foo.to_s == "foo"
более длительные явные функции как to_int
, to_s
средний, что объект может быть исходно представлен как тот тип данных. Например, Rational
класс представляет все рациональные числа, таким образом, он может быть непосредственно представлен как Fixnum (или Сверхбольшое число) целое число путем вызова to_int
.
Rational(20,4).to_int == 5
, Если Вы не можете назвать более длинный метод, это означает, что объект не может быть исходно представлен в том типе.
Так в основном, при преобразовании, если Вы ленивы с именами методов, Ruby будет ленив с преобразованием.
Я плохо знаком с рубином, и на моем первом раунде я поразил проблему относительно изменения плаваний/строк к целому числу. Я запустил с плаваний и кодировал все как f.to_int. Но когда я продвинулся и использовал тот же метод для строк, я был брошен кривая, когда он прибыл для запущения программы.
Aparently строка не имеет метод to_int , но плавает, и ints делают.
irb(main):003:0* str_val = '5.0'
=> "5.0"
irb(main):006:0> str_val.to_int
NoMethodError: undefined method `to_int' for "5.0":String
from (irb):6
irb(main):005:0* str_val.to_i
=> 5
irb(main):007:0> float_val = 5.0
=> 5.0
irb(main):008:0> float_val.to_int
=> 5
irb(main):009:0> float_val.to_i
=> 5
irb(main):010:0>
Произвольная круглая скобка бросила меня сначала также. Я видел некоторый код с и некоторых без. Это взяло меня некоторое время, чтобы понять, что любой разрабатывают, приняты.
Я думаю, что всегда хорошо использовать .length на вещах..., так как размер поддерживается почти всем, и Ruby имеет динамические типы, которые можно получить действительно странные результаты, назвав .size, когда у Вас есть неправильный тип... Я очень получил бы NoMethodError: 'длина' неопределенного метода, таким образом, я обычно никогда не называю размер на объектах в Ruby.
укусил меня несколько раз.
Также помнят, что объекты имеют идентификаторы, таким образом, я пытаюсь не использовать идентификатор вызова переменных или object_id только для предотвращения беспорядка. Если мне нужен идентификатор на Объекте USERS, лучше называть его чем-то как user_id.
Просто мои два цента
Один это ловило меня в прошлом, то, что символ новой строки (\n
) Escape sequence— среди others— не поддерживается строками в одинарных кавычках. Самой обратной косой черты оставляют. Необходимо использовать двойные кавычки для выхода для работы как ожидалось.
x = (true and false) # x is false
0 и '' верны, как Вы указали.
у Вас могут быть метод и модуль/класс тем же именем (который имеет смысл, потому что метод на самом деле добавляется для Возражения и таким образом имеет свое собственное пространство имен).
нет никакого множественного наследования, но часто "смешивание модулей" используется для добавления общепринятых методик к нескольким классам.
Я думаю" and
", и" or
" намеки на Perl, который является одним из более очевидных "родителей" Ruby (самый видный другой являющийся Smalltalk). У них обоих есть намного более низкий приоритет (ниже, чем присвоение, на самом деле, который является, куда отмеченное поведение прибывает из), чем &&
и ||
, которые являются операторами, которые необходимо использовать.
Другие вещи знать, которые не сразу очевидны:
Вы действительно не называете методы/функции, хотя это вид взглядов тот путь. Вместо этого как в Smalltalk, Вы отправляете сообщение в объект. Так method_missing
действительно больше похож message_not_understood
.
some_object.do_something(args)
эквивалентно [1 112]
some_object.send(:do_something, args) # note the :
, Символы очень широко используются. Это - те вещи, которые запускаются с :
, и они не сразу очевидны (хорошо, они не были мне), но чем ранее Вы справляетесь с ними, тем лучше.
Ruby хорошо разбирается во "вводе утки", после принципала, что, "если он идет как утка и шарлатаны как утка...", которая позволяет неофициальную замену объектов с общим подмножеством методов без любого явного наследования или смешивания отношений.
Понимание различия между классом Времени и даты. Оба отличаются и создали проблемы при использовании их в направляющих. Класс Времени иногда конфликтует с другими библиотеками классов Времени, существующими в стандартной библиотеке рубина/направляющих. Лично мне потребовалось много времени для понимания то, что точно продолжалось в моем приложении для направляющих. Позже, я изобразил, когда я сделал
Time.new
, Это относилось к некоторой библиотеке в месте, о котором я даже не знал.
Жаль, если я не ясен с тем, что я хочу сказать точно. Если другие столкнулись с подобными проблемами, повторно объясните.
Я испытал затруднения из-за mixins, которые содержат методы класса методов экземпляра и . Этот код мог бы помочь новичку:
module Displayable
# instance methods here
def display
puts name
self.class.increment_displays
end
def self.included(base)
# This module method will be called automatically
# after this module is included in a class.
# We want to add the class methods to the class.
base.extend Displayable::ClassMethods
end
module ClassMethods
# class methods here
def number_of_displays
@number_of_displays # this is a class attribute
end
def increment_displays
@number_of_displays += 1
end
def init_displays
@number_of_displays = 0
end
# this module method will be called automatically
# after this module is extended by a class.
# We want to perform some initialization on a
# class attribute.
def self.extended(base)
base.init_displays
end
end
end
class Person
include Displayable
def name; @name; end
def initialize(name); @name=name; end
end
puts Person.number_of_displays # => 0
john = Person.new "John"
john.display # => John
puts Person.number_of_displays # => 1
jack = Person.new "Jack"
jack.display # => Jack
puts Person.number_of_displays # => 2
Сначала, я думал, что у меня могли быть модули с обоими методами класса методов экземпляра и путем простого выполнения этого:
module Displayable
def display
puts name
self.class.increment_displays
end
def self.number_of_displays # WRONG!
@number_of_displays
end
[...]
end
, К сожалению, метод number_of_displays никогда не будет включаться или расширяться, потому что это - "метод класса модуля". Только "методы экземпляра модуля" могут быть включены в класс (как методы экземпляра) или расширены в класс (как методы класса). Поэтому необходимо поместить методы экземпляра mixin в модуль и методы класса mixin в другой модуль (Вы обычно помещаете методы класса в подмодуль "ClassMethods"). Благодаря включал волшебный метод, можно помочь включать и методы экземпляра и методы класса во всего одном простом, "включают Визуализуемый" вызов (как показано в примере выше).
Это смешивание будет считать каждый дисплей на на класс основание. Счетчик является атрибутом класса, таким образом, каждый класс будет иметь свое собственное (Ваша программа, вероятно, перестанет работать при получении нового класса из класса Человека начиная с , счетчик @number_of_displays для производного класса никогда не будет инициализироваться). Можно хотеть заменить @number_of_displays @@ number_of_displays для создания этого глобальным счетчиком. В этом случае каждая иерархия классов будет иметь свой собственный счетчик. Если Вы хотите глобальный и уникальный счетчик, необходимо, вероятно, сделать его атрибутом модуля.
Все это было определенно не интуитивно для меня, когда я запустил с Ruby.
я все еще не могу выяснить, как чисто сделать некоторые из этих методов смешивания частными или защищенными, хотя (только дисплей и метод number_of_displays должен быть включен как открытые методы).
Блоки действительно важны для понимания, они используются везде.
Вам не нужны круглые скобки вокруг параметров метода. Используете ли Вы их, или не ваше дело. Некоторые говорят, что необходимо всегда использовать их .
повышение Использования и спасение для обработки исключений, не бросают и ловят.
можно использовать ;
, но Вы не имеете к тому, если Вы не хотите поместить несколько вещей на одну строку.
одна вещь, которую я изучил, состояла в том, чтобы использовать оператор || = тщательно. и проявите специальную заботу, если Вы имеете дело с булевскими переменными. я обычно использовал || = b как выгода все для предоставления значения по умолчанию если все остальное отказавшее и ноль, которым остаются. но если ложь, и b верен, то желание быть присвоенным верный.
Я испытал много затруднений, поняв переменные класса, атрибуты класса и методы класса. Этот код мог бы помочь новичку:
class A
@@classvar = "A1"
@classattr = "A2"
def self.showvars
puts "@@classvar => "+@@classvar
puts "@classattr => "+@classattr
end
end
A.showvars
# displays:
# @@classvar => A1
# @classattr => A2
class B < A
@@classvar = "B1"
@classattr = "B2"
end
B.showvars
# displays:
# @@classvar => B1
# @classattr => B2
A.showvars
# displays:
# @@classvar => B1 #Class variables are shared in a class hierarchy!
# @classattr => A2 #Class attributes are not
При вызове super
без аргументов, переопределенный метод на самом деле называют с теми же аргументами как метод переопределения.
class A
def hello(name="Dan")
puts "hello #{name}"
end
end
class B < A
def hello(name)
super
end
end
B.new.hello("Bob") #=> "hello Bob"
Для фактического вызова super
без аргументов необходимо сказать super()
.
Обезьяна, исправляющая . Ruby имеет открытые классы, таким образом, их поведение может быть динамично изменено во времени выполнения...
Объекты могли бы отвечать на неопределенные методы , если method_missing
или send
был переопределен. Это использует основанный на сообщении вызов метода Ruby. направляющие ' система ActiveRecord использует это для большого эффекта.
Новички испытают затруднения из-за [1 121] методы равенства :
Эти примеры должны разъяснить первые 3 метода:
a = b = "joe"
a==b # true
a.eql? b # true
a.equal? b # true (a.object_id == b.object_id)
a = "joe"
b = "joe"
a==b # true
a.eql? b # true
a.equal? b # false (a.object_id != b.object_id)
a = 1
b = 1.0
a==b # true
a.eql? b # false (a.class != b.class)
a.equal? b # false
Примечание, что == , eql? и равный? должно всегда быть симметричным: если == b тогда b == a.
Также примечание, что == и eql? оба реализованы в объекте класса как псевдонимы к [1 131] равный? , поэтому если Вы создаете новый класс и хотите == и eql? для значения чего-то еще, чем простые идентификационные данные тогда необходимо переопределить их обоих. Например:
class Person
attr_reader name
def == (rhs)
rhs.name == self.name # compare person by their name
end
def eql? (rhs)
self == rhs
end
# never override the equal? method!
end
метод === ведет себя по-другому. В первую очередь, это не симметрично (=== b делает не , подразумевают это b === a). Как я сказал, можно считать === b как "соответствия b". Вот несколько примеров:
# === is usually simply an alias for ==
"joe" === "joe" # true
"joe" === "bob" # false
# but ranges match any value they include
(1..10) === 5 # true
(1..10) === 19 # false
(1..10) === (1..10) # false (the range does not include itself)
# arrays just match equal arrays, but they do not match included values!
[1,2,3] === [1,2,3] # true
[1,2,3] === 2 # false
# classes match their instances and instances of derived classes
String === "joe" # true
String === 1.5 # false (1.5 is not a String)
String === String # false (the String class is not itself a String)
случай оператор основан метод === :
case a
when "joe": puts "1"
when 1.0 : puts "2"
when (1..10), (15..20): puts "3"
else puts "4"
end
эквивалентно этому:
if "joe" === a
puts "1"
elsif 1.0 === a
puts "2"
elsif (1..10) === a || (15..20) === a
puts "3"
else
puts "4"
end
, Если Вы определяете новый класс, экземпляры которого представляют своего рода контейнер или диапазон (если это имеет что-то как , включают? или соответствие? метод), тогда Вы могли бы найти полезным переопределить метод === как это:
class Subnet
[...]
def include? (ip_address_or_subnet)
[...]
end
def === (rhs)
self.include? rhs
end
end
case destination_ip
when white_listed_subnet: puts "the ip belongs to the white-listed subnet"
when black_listed_subnet: puts "the ip belongs to the black-listed subnet"
[...]
end
(По крайней мере, обратите больше внимания, чем I изначально!)
Существует разница между 0..10
(две точки) и 0 ... 10
(три точки).
Итерация по рубиновым хешам не гарантируется в каком-либо определенном порядке. (Это не ошибка, это особенность)
Hash # sort
полезен, если вам нужен определенный порядок.
Связанный вопрос: Почему массив Ruby из 1000 пар ключей и значений хешей всегда находится в определенном порядке?
Блоки и методы по умолчанию возвращают значение последней строки. Добавление операторов puts
в конец в целях отладки может вызвать неприятные побочные эффекты
Следующий код удивил меня. Я думаю, что это опасная загвоздка: и легко столкнуться, и трудно отладить.
(1..5).each do |number|
comment = " is even" if number%2==0
puts number.to_s + comment.to_s
end
Это печатает:
1
2 is even
3
4 is even
5
Но если я просто добавлю comment =
anything перед блоком...
comment = nil
(1..5).each do |number|
comment = " is even" if number%2==0
puts number.to_s + comment.to_s
end
Тогда я получаю:
1
2 is even
3 is even
4 is even
5 is even
В основном, когда переменная определена только внутри блока, она уничтожается в конце блока, а затем сбрасывается на nil
при каждой итерации. Обычно именно этого вы и ожидаете. Но если переменная определена до блока, то внешняя переменная используется внутри блока, и ее значение остается постоянным между итерациями.
Одним из решений было бы написать так:
comment = number%2==0 ? " is even" : nil
Я думаю, многие люди (включая меня) склонны писать "a = b if c
" вместо "a = (c ? b : nil)
", потому что это более читабельно, но очевидно, что это имеет побочные эффекты.
1..5.each {|x| puts x}
не работает. Вы должны заключить диапазон в круглые скобки, например
(1..5).each {|x| puts x}
, чтобы вам не казалось, что вы звоните 5.each
. Я думаю, что это проблема приоритета, как и ошибка x = true и false
.